#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
策略诊断分析工具 v2.0

功能：
1. 分析指定日期为什么没有触发买入/卖出信号
2. 提供参数调整建议
3. 模拟不同参数组合的触发情况
4. ⭐ 多日期参数优化：根据多个日期进行参数调整

使用示例：
    # 单日诊断（使用列表格式）
    python strategy_diagnostic_tool.py --stock 002594.SZ --dates 20250526 --signal buy
    
    # ⭐ 多日期参数优化
    python strategy_diagnostic_tool.py --stock 002594.SZ --dates 20250521 20250523 --signal sell
    
    # 日期范围诊断
    python strategy_diagnostic_tool.py --stock 002594.SZ --start 20250501 --end 20250531
    
    或者直接修改下方的默认参数后运行：
    python strategy_diagnostic_tool.py
"""

# ============================================================================
# 📝 默认参数配置（可直接修改此处）
# ============================================================================
DEFAULT_CONFIG = {
    'stock': '002594.SZ',        # 股票代码
    'dates': ['20250206', '20250827', '20250828', '20250904', '20250905'],  # ⭐ 检查极值日期在新参数下是否仍会触发天量
    'signal': 'sell',             # 信号类型：'buy' 或 'sell'
    'start': None,               # 批量分析起始日期（可选）
    'end': None,                 # 批量分析结束日期（可选）
    'dividend_base': '20251106', # ⭐ 前复权基准日（必须与回测结束日期一致！）
}
# ============================================================================

import sys
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import argparse
from pathlib import Path

# 导入项目模块
sys.path.append(str(Path(__file__).parent))
from xtquant import xtdata
from config_loader import load_technical_config
from technical_engine import TechnicalEngine
from strategies.突破5日线 import BreakoutStrategy
import yaml


class StrategyDiagnosticTool:
    """策略诊断分析工具"""
    
    def __init__(self, stock_code, strategy_name='突破5日线', dividend_base=None):
        """
        初始化诊断工具
        
        Args:
            stock_code: 股票代码
            strategy_name: 策略名称
            dividend_base: 前复权基准日（格式：YYYYMMDD，应与回测结束日期一致）
        """
        self.stock = stock_code
        self.strategy_name = strategy_name
        self.dividend_base = dividend_base  # ⭐ 保存前复权基准日
        
        # 加载配置
        with open('config/config.yaml', 'r', encoding='utf-8') as f:
            self.config = yaml.safe_load(f)
        self.tech_config = load_technical_config()
        
        # 初始化策略
        self.strategy = BreakoutStrategy(self.config)
        
        # 初始化技术引擎
        self.tech_engine = TechnicalEngine(self.tech_config, strategy_instance=self.strategy)
        
        # ⭐ 初始化敏感度分析器（用于买入信号分析）
        try:
            from signal_validation.analyzers import TimeSensitivityAnalyzer
            from validation_config_loader import get_validation_config_loader
            
            self.sensitivity_analyzer = TimeSensitivityAnalyzer()
            self.validation_config_loader = get_validation_config_loader()
            self.buy_sensitivity_config = self.validation_config_loader.config.get('buy_sensitivity_rules', {})
        except Exception as e:
            self.sensitivity_analyzer = None
            self.validation_config_loader = None
            self.buy_sensitivity_config = {}
        
        # 连接数据源
        xtdata.enable_hello = False
        
        print("=" * 80)
        print(f"策略诊断工具初始化完成")
        print(f"  股票: {stock_code}")
        print(f"  策略: {strategy_name}")
        print(f"  技术形态: {len(self.tech_engine.pattern_detectors)}个检测器")
        print("=" * 80)
    
    def diagnose_single_day(self, target_date, signal_type='sell'):
        """
        诊断单日为什么没有触发信号
        
        Args:
            target_date: 目标日期 (str, YYYYMMDD)
            signal_type: 信号类型 ('buy' 或 'sell')
        
        Returns:
            dict: 诊断结果
        """
        print(f"\n{'=' * 80}")
        print(f"[诊断分析] {self.stock} - {target_date} - {signal_type.upper()}信号")
        print("=" * 80)
        
        # 1. 加载数据
        data = self._load_data(target_date)
        if data is None:
            return None
        
        daily_data, minute_data = data
        
        # 2. 分析主策略
        print("\n[主策略分析]")
        strategy_result = self._analyze_strategy(daily_data, minute_data, target_date, signal_type)
        
        # 3. 分析技术形态
        print("\n[技术形态分析]")
        tech_result = self._analyze_technical_patterns(minute_data, target_date)
        
        # 4. 参数调整建议
        print("\n[参数调整建议]")
        suggestions = self._generate_suggestions(strategy_result, tech_result, signal_type, minute_data)
        
        # 5. 汇总结果
        result = {
            'date': target_date,
            'signal_type': signal_type,
            'strategy_result': strategy_result,
            'tech_result': tech_result,
            'suggestions': suggestions
        }
        
        return result
    
    def _load_data(self, target_date):
        """加载日线和分钟数据"""
        try:
            # ⭐ 自动计算所需历史数据天数（考虑动态阈值配置）
            try:
                from config_loader import get_config_loader
                config_loader = get_config_loader()
                config = config_loader._config  # 获取原始配置字典
                from volume_validators.dynamic_threshold import DynamicVolumeThresholdCalculator
                required_days = DynamicVolumeThresholdCalculator.get_required_history_days(config)
            except Exception as e:
                print(f"[警告] 无法加载动态阈值配置，使用默认120天: {e}")
                required_days = 120
            
            # 计算数据范围（自动扩展以满足动态阈值需求）
            target_dt = datetime.strptime(target_date, '%Y%m%d')
            start_dt = target_dt - timedelta(days=required_days)
            
            # ⭐ 修复：移除最小日期限制，允许加载更早的数据
            # 策略需要至少30天预热期，如果限制为2025-01-01，会导致2月初数据不足
            
            start_time = start_dt.strftime('%Y%m%d')
            # ⭐ 关键：使用dividend_base作为end_time（确保前复权基准一致）
            end_time = self.dividend_base if self.dividend_base else target_dt.strftime('%Y%m%d')
            
            print(f"\n[加载数据] {start_time} ~ {end_time}")
            if self.dividend_base:
                print(f"⚠️  使用前复权基准日: {self.dividend_base}（确保与回测一致）")
            
            # 加载日线数据
            daily_data = xtdata.get_local_data(
                stock_list=[self.stock],
                period='1d',
                start_time=start_time,
                end_time=end_time,  # ⭐ 使用dividend_base
                dividend_type='front'
            )
            
            if daily_data is None:
                print(f"[错误] 无日线数据（返回None）")
                return None
            
            if self.stock not in daily_data:
                print(f"[错误] 股票代码 {self.stock} 不在返回数据中")
                return None
            
            daily_df = daily_data[self.stock]
            
            if daily_df.empty:
                print(f"[错误] 日线数据为空")
                return None
            
            # 加载分钟数据（目标日期当天）
            minute_start = f"{target_date}093000"  # 格式: 20250523093000
            minute_end = f"{target_date}150000"    # 格式: 20250523150000
            
            minute_data = xtdata.get_local_data(
                stock_list=[self.stock],
                period='1m',
                start_time=minute_start,
                end_time=minute_end,
                dividend_type='front'
            )
            
            if minute_data is None:
                print(f"[警告] 无分钟数据（可能非交易日）")
                minute_df = pd.DataFrame()
            elif self.stock not in minute_data or minute_data[self.stock].empty:
                print(f"[警告] 无分钟数据")
                minute_df = pd.DataFrame()
            else:
                minute_df = minute_data[self.stock]
            
            print(f"[成功] 日线数据: {len(daily_df)}条 | 分钟数据: {len(minute_df)}条")
            
            return daily_df, minute_df
            
        except Exception as e:
            print(f"[错误] 数据加载失败: {e}")
            return None
    
    def _analyze_strategy(self, daily_data, minute_data, target_date, signal_type):
        """分析主策略"""
        result = {
            'triggered': False,
            'conditions': [],
            'missing_conditions': [],
            'key_metrics': {},
            'minute_data': minute_data,  # ⭐ 传递分钟数据给卖出分析
            'date': target_date  # ⭐ 传递日期
        }
        
        if daily_data.empty:
            result['error'] = '无日线数据'
            return result
        
        # 计算关键指标
        target_dt = pd.to_datetime(target_date)
        # 确保索引是datetime类型
        if not isinstance(daily_data.index, pd.DatetimeIndex):
            daily_data.index = pd.to_datetime(daily_data.index)
        target_data = daily_data[daily_data.index <= target_dt]
        
        if len(target_data) < 20:
            result['error'] = '历史数据不足（需要至少20天）'
            return result
        
        # 最新价格
        current_price = target_data['close'].iloc[-1]
        
        # 均线
        ma5 = target_data['close'].rolling(window=5).mean().iloc[-1]
        ma10 = target_data['close'].rolling(window=10).mean().iloc[-1]
        ma20 = target_data['close'].rolling(window=20).mean().iloc[-1]
        
        # 量比（⭐ 调用策略的公用方法，确保计算逻辑一致）
        # 先设置策略缓存，让get_volume_ratio能正常工作
        current_volume = target_data['volume'].iloc[-1]
        
        # 使用策略的标准计算方法（相对5日均量）
        avg_volume_5 = target_data['volume'].tail(5).mean()
        volume_ratio = current_volume / avg_volume_5 if avg_volume_5 > 0 else 0
        
        # 涨跌幅
        prev_close = target_data['close'].iloc[-2] if len(target_data) >= 2 else current_price
        change_pct = (current_price - prev_close) / prev_close * 100 if prev_close > 0 else 0
        
        # 高低点
        high_60 = target_data['high'].tail(60).max()
        low_60 = target_data['low'].tail(60).min()
        price_position = (current_price - low_60) / (high_60 - low_60) if (high_60 > low_60) else 0
        
        result['key_metrics'] = {
            'price': current_price,
            'ma5': ma5,
            'ma10': ma10,
            'ma20': ma20,
            'volume_ratio': volume_ratio,
            'change_pct': change_pct,
            'price_position': price_position * 100,
            'high_60': high_60,
            'low_60': low_60
        }
        
        print(f"  价格: {current_price:.2f} | MA5: {ma5:.2f} | MA10: {ma10:.2f} | MA20: {ma20:.2f}")
        print(f"  量比: {volume_ratio:.2f} | 涨跌幅: {change_pct:+.2f}% | 价格位置: {price_position*100:.1f}%")
        
        # 分析买入/卖出条件
        if signal_type == 'sell':
            self._check_sell_conditions(result, target_data)
        else:
            self._check_buy_conditions(result, target_data, signal_type, minute_data, target_date)
        
        return result
    
    def _check_sell_conditions(self, result, data):
        """
        检查卖出条件（调用策略的真实逻辑）
        
        ⭐ 使用与买入分析一致的方式：遍历分钟数据，找到实际触发卖出的时刻
        """
        metrics = result['key_metrics']
        
        # ⭐ 关键改进：使用分钟数据分析（与买入分析一致）
        # 获取分钟数据（应该在_analyze_strategy中传入）
        minute_data = result.get('minute_data')
        
        if minute_data is None or minute_data.empty:
            # 回退到日线分析（不准确，但至少能工作）
            print(f"  [警告] 无分钟数据，使用日线数据分析（可能不准确）")
            self._check_sell_conditions_daily(result, data)
            return
        
        try:
            # 准备历史数据（前一日之前的数据）
            target_dt = pd.to_datetime(result.get('date', ''))
            if not isinstance(data.index, pd.DatetimeIndex):
                data.index = pd.to_datetime(data.index)
            
            prev_day_data = data[data.index < target_dt]
            if len(prev_day_data) < 30:
                print(f"  [错误] 历史数据不足")
                result['triggered'] = False
                return
            
            # 构造 hist_np（与回测系统完全一致）
            # 为历史数据准备时间格式（与回测系统一致）
            hist_time_values = []
            for d in prev_day_data.index:
                if isinstance(d, pd.Timestamp):
                    hist_time_values.append(d.strftime('%Y%m%d'))
                else:
                    hist_time_values.append(str(d).replace('-', '').replace('/', '')[:8])
            
            hist_np = {
                'close': prev_day_data['close'].values,
                'open': prev_day_data['open'].values,
                'high': prev_day_data['high'].values,
                'low': prev_day_data['low'].values,
                'volume': prev_day_data['volume'].values,
                'time': hist_time_values  # ⭐ 添加time字段（与回测系统一致）
            }
            
            # ⭐ 设置流通股本（与买入分析一致）
            if self.stock not in self.strategy.float_shares or self.strategy.float_shares[self.stock] == 0:
                default_float_shares = 3_000_000_000  # 默认30亿股
                if not prev_day_data.empty:
                    recent_volume = prev_day_data['volume'].tail(20).mean()
                    if recent_volume > 0:
                        estimated_shares = recent_volume * 100
                        if estimated_shares > 1_000_000_000:
                            default_float_shares = estimated_shares
                self.strategy.float_shares[self.stock] = int(default_float_shares)
            
            # ⭐ 遍历每分钟，找到第一个触发卖出的时刻（与买入分析一致）
            sell_triggered_time = None
            sell_result = None
            
            for minute_idx, (idx, row) in enumerate(minute_data.iterrows()):
                time_obj = idx if isinstance(idx, pd.Timestamp) else pd.to_datetime(idx)
                time_str = time_obj.strftime('%H:%M')
                
                # 获取到当前分钟的累积数据
                current_slice = minute_data.iloc[:minute_idx+1]
                
                # 计算实际交易分钟数
                hour = time_obj.hour
                minute_val = time_obj.minute
                if hour < 11 or (hour == 11 and minute_val <= 30):
                    actual_trading_minutes = (hour - 9) * 60 + minute_val - 30
                elif hour >= 13:
                    actual_trading_minutes = 120 + (hour - 13) * 60 + minute_val
                else:
                    actual_trading_minutes = 120
                actual_trading_minutes = max(1, actual_trading_minutes)
                
                # 计算累积成交量和量比（与回测系统完全一致）
                current_volume = int(current_slice['volume'].sum())
                
                # ⭐ 使用与回测系统完全相同的量比计算方式
                if len(prev_day_data) >= 5:
                    recent_5_volumes = prev_day_data['volume'].tail(5)
                    avg_volume_5d = recent_5_volumes.mean()
                    
                    # 与回测系统一致的计算方式
                    daily_trading_minutes = 240  # A股每日交易时间240分钟
                    past_5_days_avg_per_minute = avg_volume_5d / daily_trading_minutes
                    
                    # 使用实际交易分钟数（与回测系统一致）
                    current_trading_minutes = min(actual_trading_minutes, daily_trading_minutes)
                    current_trading_minutes = max(1, current_trading_minutes)  # 至少1分钟
                    
                    # 计算量比
                    expected_volume = past_5_days_avg_per_minute * current_trading_minutes
                    volume_ratio = current_volume / expected_volume if expected_volume > 0 else 0
                else:
                    volume_ratio = 0
                
                # 构造 today_data（与回测系统完全一致）
                # ⭐ lastClose的计算：使用hist_np的倒数第二个（前一日收盘价，与回测系统一致）
                if len(hist_np['close']) > 1:
                    last_close = float(hist_np['close'][-2])  # 倒数第二个是前一日收盘价
                elif len(hist_np['close']) > 0:
                    last_close = float(hist_np['close'][-1])
                else:
                    last_close = float(row['close'])
                
                today_data = {
                    'open': float(current_slice['open'].iloc[0]),
                    'high': float(current_slice['high'].max()),
                    'low': float(current_slice['low'].min()),
                    'last': float(row['close']),
                    'volume': current_volume,
                    'volRatio': volume_ratio,  # ⭐ 盘中量比
                    'lastClose': last_close,  # ⭐ 与回测系统一致
                    'time': time_obj  # ⭐ 时间字段
                }
                
                # 设置策略缓存
                self.strategy.hist_np_cache[self.stock] = hist_np
                self.strategy.today_data[self.stock] = today_data
                
                # 预计算指标
                self.strategy.precalculate_indicators(self.stock, today_data, hist_np)
                
                # ⭐ 调用策略的卖出逻辑
                temp_sell_result = self.strategy.check_sell_conditions(self.stock)
                
                # 如果策略产生卖出信号，需要通过验证系统（与回测一致）
                if temp_sell_result and temp_sell_result.get('should_sell', False):
                    # ⭐ 关键：调用信号验证系统（与回测系统一致）
                    sell_reason = temp_sell_result.get('reason', '')
                    validated = self._validate_sell_signal(
                        minute_data, minute_idx, time_obj, sell_reason
                    )
                    
                    # 只有通过验证的信号才记录
                    if validated:
                        sell_triggered_time = time_str
                        sell_result = temp_sell_result
                        sell_result['trigger_time'] = time_str  # 记录触发时刻
                        sell_result['trigger_volume_ratio'] = volume_ratio  # 记录触发时的量比
                        sell_result['validated'] = True  # 标记已通过验证
                        break  # 找到第一个通过验证的触发点就停止
            
            # 4. 解析结果（使用找到的触发时刻的数据）
            if sell_result and sell_result.get('should_sell', False):
                result['triggered'] = True
                result['sell_reason'] = sell_result.get('reason', '未知原因')
                result['sell_details'] = sell_result.get('details', {})
                result['trigger_time'] = sell_result.get('trigger_time', '未知')
                result['trigger_volume_ratio'] = sell_result.get('trigger_volume_ratio', 0)
                
                # 解析触发的条件类型
                reason = result['sell_reason']
                if '条件A' in reason:
                    condition_type = 'A-高位缩量'
                elif '条件B1' in reason:
                    condition_type = 'B1-天量出货'
                elif '条件B2' in reason:
                    condition_type = 'B2-放量滞涨'
                elif '条件C' in reason:
                    condition_type = 'C-跌破5日线'
                elif '条件D' in reason:
                    condition_type = 'D-技术形态'
                elif '条件E' in reason:
                    condition_type = 'E-趋势转弱'
                else:
                    condition_type = '未知条件'
                
                result['condition_type'] = condition_type
                result['conditions'].append(f"{condition_type}: {reason}")
                
                # 输出详细信息
                print(f"  [✅ 触发] {condition_type}")
                print(f"     触发时刻: {result['trigger_time']}")  # ⭐ 显示触发时刻
                print(f"     触发量比: {result['trigger_volume_ratio']:.2f}")  # ⭐ 显示触发时的量比
                print(f"     原因: {reason}")
                
                # 输出关键参数
                details = result['sell_details']
                if 'current_price' in details:
                    print(f"     当前价: {details['current_price']:.2f}")
                if 'previous_high' in details:
                    print(f"     前高: {details['previous_high']:.2f}")
                if 'price_change_pct' in details:
                    print(f"     涨幅: {details['price_change_pct']:+.2f}%")
                
            else:
                result['triggered'] = False
                # 分析未触发的原因
                print(f"  [未触发] 所有卖出条件均不满足")
                
                # 检查各个条件接近程度
                stock_type = today_data.get('stock_type', 'large')
                volume_ratio = metrics['volume_ratio']
                
                # 检查条件A（高位缩量）
                params_a = self.config.get('sell_high_shrink', {}).get(stock_type, {})
                if params_a and metrics['price_position'] >= 80:
                    if volume_ratio >= params_a.get('volume_ratio', 0.8):
                        result['missing_conditions'].append(
                            f"量比过高 ({volume_ratio:.2f} >= {params_a.get('volume_ratio', 0.8)})"
                        )
                elif metrics['price_position'] < 80:
                    result['missing_conditions'].append(
                        f"价格位置不足 ({metrics['price_position']:.1f}% < 80%)"
                    )
                
                # 检查条件B1/B2（放量）
                params_b1 = self.config.get('sell_extreme_volume', {}).get(stock_type, {})
                params_b2 = self.config.get('sell_volume_lag', {}).get(stock_type, {})
                
                if len(data) >= 30:
                    previous_high = float(data['close'].iloc[-30:-1].max())
                    current_price = metrics['price']
                    
                    if current_price > previous_high * 1.01:
                        # 已突破前高，检查量比
                        if params_b1 and volume_ratio <= params_b1.get('volume_ratio', 3.5):
                            result['missing_conditions'].append(
                                f"量比不足B1标准 ({volume_ratio:.2f} <= {params_b1.get('volume_ratio', 3.5)})"
                            )
                        if params_b2 and volume_ratio <= params_b2.get('volume_ratio', 2.0):
                            result['missing_conditions'].append(
                                f"量比不足B2标准 ({volume_ratio:.2f} <= {params_b2.get('volume_ratio', 2.0)})"
                            )
                    else:
                        result['missing_conditions'].append(
                            f"未突破前高 (当前{current_price:.2f} <= 前高{previous_high:.2f}×1.01)"
                        )
                
                # 检查条件C（跌破MA5）
                if metrics['price'] >= metrics['ma5']:
                    result['missing_conditions'].append(f"未跌破MA5 (价格{metrics['price']:.2f} >= MA5 {metrics['ma5']:.2f})")
                
                # 输出未满足的条件
                for missing in result['missing_conditions']:
                    print(f"     - {missing}")
            
            # 5. 清理临时数据
            if self.stock in self.strategy.hist_np_cache:
                del self.strategy.hist_np_cache[self.stock]
            if self.stock in self.strategy.today_data:
                del self.strategy.today_data[self.stock]
                
        except Exception as e:
            print(f"  [错误] 调用策略卖出逻辑失败: {e}")
            import traceback
            traceback.print_exc()
            result['triggered'] = False
            result['error'] = str(e)
    
    def _validate_sell_signal(self, minute_data, current_idx, current_time, sell_reason):
        """
        验证卖出信号（与回测系统的验证逻辑一致）
        
        Args:
            minute_data: 分钟K线数据
            current_idx: 当前分钟索引
            current_time: 当前时间
            sell_reason: 卖出原因
            
        Returns:
            bool: 是否通过验证
        """
        try:
            # 导入信号验证系统
            from signal_validation.checker import EnhancedSellSignalChecker
            
            # 初始化验证器（如果还没有）
            if not hasattr(self, 'sell_signal_checker'):
                self.sell_signal_checker = EnhancedSellSignalChecker()
            
            # 构建验证需要的DataFrame（当前分钟及之前的数据）
            stock_data = minute_data.iloc[:current_idx+1].copy()
            
            # 调用验证系统
            confirmed, details = self.sell_signal_checker.check_sell_signal(
                stock_data=stock_data,
                current_index=current_idx,
                current_time=current_time,
                sell_reason=sell_reason,
                stock_code=self.stock
            )
            
            return confirmed
            
        except Exception as e:
            # 如果验证系统出错，保守处理：放行信号
            print(f"      ⚠️  信号验证失败: {e}，放行信号")
            return True
    
    def _check_sell_conditions_daily(self, result, data):
        """
        使用日线数据检查卖出条件（回退方案，不准确）
        """
        try:
            # 构造 hist_np
            hist_np = {
                'close': data['close'].values,
                'open': data['open'].values,
                'high': data['high'].values,
                'low': data['low'].values,
                'volume': data['volume'].values,
            }
            
            # 构造 today_data（全天数据）
            last_row = data.iloc[-1]
            current_volume = float(last_row['volume'])
            
            # 计算量比（相对5日均量）
            if len(data) >= 6:
                avg_volume_5 = data['volume'].iloc[-6:-1].mean()
                volume_ratio = current_volume / avg_volume_5 if avg_volume_5 > 0 else 0
            else:
                volume_ratio = 0
            
            last_close = float(data['close'].iloc[-2]) if len(data) >= 2 else float(last_row['close'])
            
            today_data = {
                'open': float(last_row['open']),
                'high': float(last_row['high']),
                'low': float(last_row['low']),
                'last': float(last_row['close']),
                'close': float(last_row['close']),
                'volume': current_volume,
                'volRatio': volume_ratio,
                'lastClose': last_close,
            }
            
            # 设置策略缓存
            self.strategy.hist_np_cache[self.stock] = hist_np
            self.strategy.today_data[self.stock] = today_data
            
            # 预计算指标
            self.strategy.precalculate_indicators(self.stock, today_data, hist_np)
            
            # 调用策略卖出逻辑
            sell_result = self.strategy.check_sell_conditions(self.stock)
            
            # 解析结果（同主逻辑）
            if sell_result and sell_result.get('should_sell', False):
                result['triggered'] = True
                result['sell_reason'] = sell_result.get('reason', '未知原因')
                result['sell_details'] = sell_result.get('details', {})
                
                reason = result['sell_reason']
                if '条件A' in reason:
                    condition_type = 'A-高位缩量'
                elif '条件B1' in reason:
                    condition_type = 'B1-天量出货'
                elif '条件B2' in reason:
                    condition_type = 'B2-放量滞涨'
                elif '条件C' in reason:
                    condition_type = 'C-跌破5日线'
                elif '条件D' in reason:
                    condition_type = 'D-技术形态'
                elif '条件E' in reason:
                    condition_type = 'E-趋势转弱'
                else:
                    condition_type = '未知条件'
                
                result['condition_type'] = condition_type
                result['conditions'].append(f"{condition_type}: {reason}")
                
                print(f"  [✅ 触发] {condition_type} (日线数据)")
                print(f"     全天量比: {volume_ratio:.2f}")
                print(f"     原因: {reason}")
            else:
                result['triggered'] = False
                print(f"  [未触发] 所有卖出条件均不满足 (日线数据)")
            
            # 清理
            if self.stock in self.strategy.hist_np_cache:
                del self.strategy.hist_np_cache[self.stock]
            if self.stock in self.strategy.today_data:
                del self.strategy.today_data[self.stock]
                
        except Exception as e:
            print(f"  [错误] 日线卖出分析失败: {e}")
            result['triggered'] = False
    
    def _check_buy_conditions(self, result, data, signal_type='buy', minute_data=None, target_date=None):
        """检查买入条件"""
        metrics = result['key_metrics']
        
        # 获取策略配置中的买入条件阈值
        buy_config = self.config.get('trading_rules', {}).get('buy', {})
        
        # 条件1: 突破MA5
        if metrics['price'] > metrics['ma5']:
            result['conditions'].append(f"突破MA5 (价格{metrics['price']:.2f} > MA5 {metrics['ma5']:.2f})")
        else:
            result['missing_conditions'].append(f"未突破MA5 (价格{metrics['price']:.2f} <= MA5 {metrics['ma5']:.2f})")
        
        # 条件2: 多头排列
        if metrics['ma5'] > metrics['ma10'] > metrics['ma20']:
            result['conditions'].append(f"多头排列 (MA5 {metrics['ma5']:.2f} > MA10 {metrics['ma10']:.2f} > MA20 {metrics['ma20']:.2f})")
        else:
            result['missing_conditions'].append(f"非多头排列 (MA5 {metrics['ma5']:.2f}, MA10 {metrics['ma10']:.2f}, MA20 {metrics['ma20']:.2f})")
        
        # 条件3: 量价配合
        min_volume_ratio = buy_config.get('min_volume_ratio', 1.0)
        if metrics['volume_ratio'] >= min_volume_ratio:
            result['conditions'].append(f"量价配合 (量比{metrics['volume_ratio']:.2f} >= {min_volume_ratio})")
        else:
            result['missing_conditions'].append(f"量比不足 ({metrics['volume_ratio']:.2f} < {min_volume_ratio})")
        
        # 综合判断（买入需要3个条件都满足）
        result['triggered'] = len(result['conditions']) == 3  # 必须满足所有3个条件
        
        # 输出结果
        print(f"\n  买入条件检查结果 ({len(result['conditions'])}/3):")
        for condition in result['conditions']:
            print(f"     ✅ {condition}")
        for missing in result['missing_conditions']:
            print(f"     ❌ {missing}")
        
        if result['triggered']:
            print(f"\n  ✅ [触发] 所有条件满足，可以买入")
        else:
            print(f"\n  ❌ [未触发] 条件不足，无法买入")
            
        # ⭐ 如果是买入信号，显示敏感度分析
        if signal_type == 'buy':
            self._analyze_buy_sensitivity(minute_data, target_date)
            
        # ⭐ 如果是买入信号，且使用了分钟数据，分析分时情况
        if signal_type == 'buy' and minute_data is not None and not minute_data.empty:
            print(f"\n  [分时分析] 检查分时数据中是否有满足买入条件的时刻...")
            buy_triggers = self._analyze_intraday_buy_conditions(minute_data, data, target_date, metrics)
            # 保存触发信息供参数优化使用
            result['intraday_buy_triggers'] = buy_triggers
    
    def _analyze_technical_patterns(self, minute_data, target_date):
        """分析技术形态"""
        result = {
            'patterns_detected': [],
            'patterns_checked': [],
            'signals': []
        }
        
        if minute_data.empty:
            result['error'] = '无分钟数据'
            print("  [跳过] 无分钟数据，跳过技术形态分析")
            return result
        
        print(f"  分钟K线数量: {len(minute_data)}条")
        
        # 确保索引是datetime类型
        if not isinstance(minute_data.index, pd.DatetimeIndex):
            minute_data.index = pd.to_datetime(minute_data.index)
        
        # 逐分钟检测技术形态（使用evaluate_sell_signal来检查是否触发独立模式）
        detected_count = 0
        independent_triggered = False
        max_strength_signal = None
        max_strength = 0
        
        for idx in minute_data.index:
            current_data = minute_data[minute_data.index <= idx]
            
            if len(current_data) < 10:
                continue
            
            # 模拟持仓信息（假设已持仓，盈亏5%）
            position_info = {
                'cost': current_data['close'].iloc[0],
                'current_price': current_data['close'].iloc[-1],
                'profit_ratio': 0.05
            }
            
            # ⭐ 使用evaluate_sell_signal来检查是否触发独立模式（条件D）
            # 这是实际回测中使用的方法
            try:
                # 构建today_data（分时模式需要的格式）
                today_data = {
                    'open': float(current_data['open'].iloc[0]),
                    'high': float(current_data['high'].max()),
                    'low': float(current_data['low'].min()),
                    'last': float(current_data['close'].iloc[-1]),
                    'volume': int(current_data['volume'].sum()),
                    'time': idx
                }
                
                tech_result = self.tech_engine.evaluate_sell_signal(
                    stock=self.stock,
                    strategy_signal=None,  # 不传入策略信号，只检查独立触发
                    today_data=today_data,  # 分时模式使用today_data
                    position_info=position_info,
                    mode='intraday'  # 分时模式
                )
                
                if tech_result.get('action') == 'independent':
                    independent_triggered = True
                    signal = tech_result.get('signal', {})
                    result['signals'].append({
                        'time': idx.strftime('%H:%M:%S'),
                        'pattern': signal.get('pattern', '未知'),
                        'reason': signal.get('reason', ''),
                        'strength': signal.get('tech_strength', 0),
                        'action': 'independent',
                        'priority': signal.get('priority', 0)
                    })
                    detected_count += 1
                    if detected_count <= 5:
                        print(f"  {idx.strftime('%H:%M:%S')} - {signal.get('pattern', '未知')}: 【条件D】{signal.get('reason', '')} (强度{signal.get('tech_strength', 0):.1f})")
                elif tech_result.get('action') == 'enhanced':
                    # 只增强，未独立触发
                    signal = tech_result.get('signal', {})
                    strength = signal.get('tech_strength', 0)
                    if strength > max_strength:
                        max_strength = strength
                        max_strength_signal = {
                            'time': idx.strftime('%H:%M:%S'),
                            'pattern': signal.get('pattern', '未知'),
                            'reason': signal.get('reason', ''),
                            'strength': strength,
                            'action': 'enhanced'
                        }
            except Exception as e:
                # 如果evaluate失败，回退到analyze_all_patterns
                signals = self.tech_engine.analyze_all_patterns(
                    stock=self.stock,
                    stock_data=current_data,
                    position_info=position_info
                )
                
                if signals:
                    detected_count += 1
                    for signal in signals:
                        strength = signal.get('strength', 0)
                        if strength > max_strength:
                            max_strength = strength
                            max_strength_signal = {
                                'time': idx.strftime('%H:%M:%S'),
                                'pattern': signal.get('pattern', '未知'),
                                'reason': signal.get('reason', ''),
                                'strength': strength
                            }
                        result['signals'].append({
                            'time': idx.strftime('%H:%M:%S'),
                            'pattern': signal.get('pattern', '未知'),
                            'reason': signal.get('reason', ''),
                            'strength': strength,
                            'action': '',
                            'priority': signal.get('priority', 0)
                        })
                        
                        # 只显示前5个
                        if detected_count <= 5:
                            print(f"  {idx.strftime('%H:%M:%S')} - {signal.get('pattern', '未知')}: {signal.get('reason', '')} (强度{strength:.1f})")
        
        if detected_count > 5:
            print(f"  ... 还有{detected_count - 5}个信号（共{detected_count}个）")
        
        # 保存最大强度信号用于后续分析
        if max_strength_signal:
            result['max_strength_signal'] = max_strength_signal
            result['max_strength'] = max_strength
        
        if detected_count == 0:
            print(f"  [未检测到] 全天未检测到技术形态信号")
            
            # 分析为什么没有触发
            self._analyze_why_no_tech_signal(minute_data, result)
        else:
            if independent_triggered:
                print(f"  [检测到] {detected_count}个技术形态信号，其中条件D已触发")
            else:
                print(f"  [检测到] {detected_count}个技术形态信号")
                
                # ⭐ 分析为什么没有触发独立信号（条件D）
                print(f"  [分析] 检测到技术形态，但未触发条件D（独立触发）")
                self._analyze_why_no_independent_signal(minute_data, result)
        
        return result
    
    def _analyze_why_no_tech_signal(self, minute_data, result):
        """分析为什么没有触发技术信号"""
        print("\n  [诊断] 为什么没有触发技术形态？")
        
        # 获取技术形态配置
        upper_shadow_config = self.tech_config.get('upper_shadow', {})
        sell_config = upper_shadow_config.get('sell_signals', {})
        
        # 分析每根K线
        issue_summary = {
            'min_kline_range': 0,
            'shadow_ratio': 0,
            'volume_min': 0,
            'position_min': 0,
            'strength': 0
        }
        
        for idx in minute_data.index:
            row = minute_data.loc[idx]
            open_price = row['open']
            high = row['high']
            low = row['low']
            close = row['close']
            
            # 计算上影线
            body_top = max(open_price, close)
            total = high - low
            upper = high - body_top
            upper_ratio = upper / total if total > 0 else 0
            
            if upper_ratio < 0.80:  # 只关注上影线明显的K线
                continue
            
            # 检查各个条件
            current_data = minute_data[minute_data.index <= idx]
            
            # 1. K线振幅
            min_range = upper_shadow_config.get('min_kline_range', 0.5)
            if total < min_range:
                issue_summary['min_kline_range'] += 1
            
            # 2. 上影线比例
            shadow_threshold = sell_config.get('large_cap', {}).get('shadow_ratio', 0.45)
            if upper_ratio < shadow_threshold:
                issue_summary['shadow_ratio'] += 1
            
            # 3. 量比
            if len(current_data) >= 20:
                avg_volume = current_data['volume'].tail(20).mean()
                volume_ratio = row['volume'] / avg_volume if avg_volume > 0 else 0
                volume_threshold = sell_config.get('large_cap', {}).get('volume_min', 0.8)
                if volume_ratio < volume_threshold:
                    issue_summary['volume_min'] += 1
            
            # 4. 价格位置
            if len(current_data) >= 60:
                lookback = current_data[-60:]
                price_max = lookback['high'].max()
                price_min = lookback['low'].min()
                price_pos = (high - price_min) / (price_max - price_min) if (price_max > price_min) else 0
                position_threshold = sell_config.get('large_cap', {}).get('position_min', 0.50)
                if price_pos < position_threshold:
                    issue_summary['position_min'] += 1
        
        # 输出诊断结果
        print(f"     未达标次数统计（上影线>=80%的K线）:")
        print(f"       - K线振幅不足: {issue_summary['min_kline_range']}次")
        print(f"       - 上影线比例不足: {issue_summary['shadow_ratio']}次")
        print(f"       - 量比不足: {issue_summary['volume_min']}次")
        print(f"       - 价格位置不足: {issue_summary['position_min']}次")
        
        result['diagnosis'] = issue_summary
    
    def _analyze_why_no_independent_signal(self, minute_data, result):
        """分析为什么没有触发条件D（独立触发）"""
        if minute_data.empty:
            return
        
        # ⭐ 使用全天数据（日K线）分析，与parameter_optimizer保持一致
        daily_high = minute_data['high'].max()
        daily_low = minute_data['low'].min()
        daily_close = minute_data['close'].iloc[-1]
        daily_open = minute_data['open'].iloc[0]
        daily_volume = minute_data['volume'].sum()
        
        # 计算日K线上影线比例
        daily_range = daily_high - daily_low
        body_top = max(daily_open, daily_close)
        daily_upper_shadow = daily_high - body_top
        daily_upper_shadow_ratio = daily_upper_shadow / daily_range if daily_range > 0 else 0
        
        # 获取配置阈值
        upper_shadow_config = self.tech_config.get('upper_shadow', {})
        sell_config = upper_shadow_config.get('sell_signals', {})
        large_cap_config = sell_config.get('large_cap', {})  # 简化：假设是大盘股
        independent_config = upper_shadow_config.get('independent_mode', {})
        
        threshold_shadow = large_cap_config.get('shadow_ratio', 0.35)
        threshold_volume = large_cap_config.get('volume_min', 0.8)
        threshold_position = large_cap_config.get('position_min', 0.70)
        min_strength = independent_config.get('min_strength', 3.0)
        
        # 计算量比（需要使用日线数据）
        # 简化：使用分钟数据的平均值估算
        avg_volume_per_min = minute_data['volume'].mean()
        estimated_daily_volume = avg_volume_per_min * 240  # 假设240分钟
        
        # 计算价格位置（需要日线数据，这里简化处理）
        # 实际应该使用60天历史数据
        
        print(f"    【日K线数据】:")
        print(f"      上影线比例: {daily_upper_shadow_ratio:.2%} (阈值: {threshold_shadow:.2%})")
        if daily_upper_shadow_ratio < threshold_shadow:
            gap = threshold_shadow - daily_upper_shadow_ratio
            suggested = daily_upper_shadow_ratio * 0.95
            print(f"      ❌ 上影线比例不足，差异: {gap:.2%}")
            print(f"      💡 建议: 降至 {suggested:.2%} (当前值×95%)")
        
        # 如果有最强信号，显示强度对比
        max_strength = result.get('max_strength', 0)
        if max_strength > 0:
            print(f"    【信号强度】:")
            print(f"      最大强度: {max_strength:.2f} (独立触发阈值: {min_strength:.2f})")
            if max_strength < min_strength:
                gap = min_strength - max_strength
                print(f"      ❌ 强度不足，差异: {gap:.2f}")
                print(f"      💡 建议: 独立触发阈值降至 {max_strength * 0.95:.2f} (当前最大值×95%)")
        elif result.get('signals'):
            # 回退：从signals中找最大强度
            max_strength_signal = max(result['signals'], key=lambda x: x.get('strength', 0))
            max_strength = max_strength_signal.get('strength', 0)
            if max_strength > 0:
                print(f"    【信号强度】:")
                print(f"      最大强度: {max_strength:.2f} (独立触发阈值: {min_strength:.2f})")
                if max_strength < min_strength:
                    gap = min_strength - max_strength
                    print(f"      ❌ 强度不足，差异: {gap:.2f}")
                    print(f"      💡 建议: 独立触发阈值降至 {max_strength * 0.95:.2f} (当前最大值×95%)")
    
    def _generate_suggestions(self, strategy_result, tech_result, signal_type, minute_data=None):
        """生成参数调整建议（⭐ 基于日K线数据，参考parameter_optimizer）"""
        suggestions = []
        
        # ⭐ 主策略建议：处理"已触发但希望避免触发"的情况（反推参数）
        if strategy_result.get('triggered', False) and signal_type == 'sell':
            print("  [参数反推] 已触发卖出信号，反推避免触发的参数:")
            
            metrics = strategy_result['key_metrics']
            condition_type = strategy_result.get('condition_type', '')
            trigger_volume_ratio = strategy_result.get('trigger_volume_ratio', 0)
            
            # B1-天量出货的反推
            if 'B1' in condition_type or '天量' in condition_type:
                print(f"     📊 当前情况:")
                print(f"       触发条件: {condition_type}")
                print(f"       触发量比: {trigger_volume_ratio:.2f}")
                
                # 检查是否使用动态阈值
                from config_loader import get_config_loader
                config_loader = get_config_loader()
                config = config_loader._config
                dynamic_config = config.get('dynamic_volume_threshold', {})
                enabled = dynamic_config.get('enabled', False)
                
                if enabled:
                    # 使用动态阈值
                    base_large = dynamic_config.get('base_thresholds', {}).get('large', 4.5)
                    min_threshold = base_large * 0.9  # 下限保护
                    
                    print(f"       当前动态阈值配置:")
                    print(f"         base_thresholds.large: {base_large}")
                    print(f"         下限保护: {min_threshold:.2f} (base_large * 0.9)")
                    
                    # 反推：需要提高阈值，使得 trigger_volume_ratio < 新阈值
                    # 建议：新阈值 = trigger_volume_ratio * 1.05（留5%安全边际）
                    suggested_threshold = trigger_volume_ratio * 1.05
                    suggested_base_large = suggested_threshold / 0.9  # 反推base_large
                    
                    print(f"\n     💡 反推建议（避免触发）:")
                    print(f"       方案1: 提高 base_thresholds.large")
                    print(f"         当前: {base_large}")
                    print(f"         建议: {suggested_base_large:.2f} (下限={suggested_threshold:.2f})")
                    print(f"         理由: 触发量比{trigger_volume_ratio:.2f} < 新下限{suggested_threshold:.2f}，不会触发")
                    
                    suggestions.append({
                        'type': 'dynamic_threshold',
                        'parameter': 'dynamic_volume_threshold.base_thresholds.large',
                        'current_value': base_large,
                        'suggested_value': suggested_base_large,
                        'reason': f'避免触发：当前量比{trigger_volume_ratio:.2f}，建议提高base_large至{suggested_base_large:.2f}（下限={suggested_threshold:.2f}）'
                    })
                    
                    # 方案2: 调整下限保护比例（从0.9降到更低）
                    alternative_ratio = trigger_volume_ratio / base_large  # 反推比例
                    if alternative_ratio < 0.9:
                        print(f"\n       方案2: 降低下限保护比例")
                        print(f"         当前: 0.9 (base_large * 0.9)")
                        print(f"         建议: {alternative_ratio:.2f} (base_large * {alternative_ratio:.2f})")
                        print(f"         理由: 触发量比{trigger_volume_ratio:.2f} < base_large*{alternative_ratio:.2f}={base_large*alternative_ratio:.2f}，不会触发")
                        print(f"         ⚠️  注意：需要修改代码中的下限保护计算逻辑")
                else:
                    # 使用固定阈值
                    sell_config = config.get('sell_extreme_volume', {})
                    large_config = sell_config.get('large', {})
                    current_threshold = large_config.get('volume_ratio', 4.5)
                    
                    print(f"       当前固定阈值配置:")
                    print(f"         sell_extreme_volume.large.volume_ratio: {current_threshold}")
                    
                    # 反推：需要提高阈值
                    suggested_threshold = trigger_volume_ratio * 1.05
                    
                    print(f"\n     💡 反推建议（避免触发）:")
                    print(f"       提高 sell_extreme_volume.large.volume_ratio")
                    print(f"         当前: {current_threshold}")
                    print(f"         建议: {suggested_threshold:.2f}")
                    print(f"         理由: 触发量比{trigger_volume_ratio:.2f} < 新阈值{suggested_threshold:.2f}，不会触发")
                    
                    suggestions.append({
                        'type': 'fixed_threshold',
                        'parameter': 'sell_extreme_volume.large.volume_ratio',
                        'current_value': current_threshold,
                        'suggested_value': suggested_threshold,
                        'reason': f'避免触发：当前量比{trigger_volume_ratio:.2f}，建议提高阈值至{suggested_threshold:.2f}'
                    })
        
        # 主策略建议：处理"未触发"的情况
        if not strategy_result.get('triggered', False):
            print("  [建议] 主策略参数调整:")
            
            metrics = strategy_result['key_metrics']
            
            for missing in strategy_result.get('missing_conditions', []):
                if '量比' in missing and '过高' in missing:
                    # 量比过高，说明当前策略认为应该放量卖出，但配置要求缩量
                    current_ratio = metrics['volume_ratio']
                    # 获取配置阈值
                    sell_config = self.config.get('trading_rules', {}).get('sell', {})
                    threshold = sell_config.get('high_shrink_volume_ratio', 0.8)
                    
                    if current_ratio > threshold:
                        # 实际量比高于阈值，说明不符合缩量条件
                        print(f"     - 量比过高: 实际{current_ratio:.2f} > 阈值{threshold:.2f}")
                        print(f"       说明: 当前为放量，不符合高位缩量卖出条件")
                        print(f"       建议: 如需触发，可提高缩量阈值至 {current_ratio * 1.1:.2f}")
                
                if '量比' in missing and '不足' in missing:
                    current_ratio = metrics['volume_ratio']
                    threshold = self.config.get('trading_rules', {}).get('sell', {}).get('ma5_break_volume_ratio', 1.2)
                    suggested = current_ratio * 0.9
                    suggestions.append({
                        'type': 'strategy',
                        'parameter': 'ma5_break_volume_ratio',
                        'current_value': threshold,
                        'suggested_value': suggested,
                        'reason': f'当前量比{current_ratio:.2f}不足，建议降低阈值至{suggested:.2f}'
                    })
                    print(f"     - 降低量比阈值: 当前{threshold:.2f} → 建议{suggested:.2f} (实际值{current_ratio:.2f}×90%)")
                
                if '价格位置' in missing and '不足' in missing:
                    current_pos = metrics['price_position']
                    suggested = current_pos * 0.95
                    suggestions.append({
                        'type': 'strategy',
                        'parameter': 'high_shrink_position_threshold',
                        'current_value': 80.0,
                        'suggested_value': suggested,
                        'reason': f'当前价格位置{current_pos:.1f}%不足，建议降低阈值至{suggested:.1f}%'
                    })
                    print(f"     - 降低价格位置阈值: 当前80.0% → 建议{suggested:.1f}% (实际值{current_pos:.1f}%×95%)")
                
                if '未跌破MA5' in missing:
                    price = metrics['price']
                    ma5 = metrics['ma5']
                    gap = price - ma5
                    print(f"     - 未跌破MA5: 价格{price:.2f} > MA5{ma5:.2f}, 差距{gap:.2f}元")
                    print(f"       说明: 价格仍在MA5之上，不符合跌破条件")
        
        # ⭐ 技术形态建议（基于日K线数据）
        if tech_result.get('signals'):
            # 检查是否触发独立信号
            independent_signals = [s for s in tech_result.get('signals', []) if s.get('action') == 'independent']
            if not independent_signals and minute_data and not minute_data.empty:
                print("  [建议] 技术形态参数调整（基于日K线数据）:")
                
                # 使用全天数据计算
                daily_high = minute_data['high'].max()
                daily_low = minute_data['low'].min()
                daily_close = minute_data['close'].iloc[-1]
                daily_open = minute_data['open'].iloc[0]
                
                daily_range = daily_high - daily_low
                body_top = max(daily_open, daily_close)
                daily_upper_shadow = daily_high - body_top
                daily_upper_shadow_ratio = daily_upper_shadow / daily_range if daily_range > 0 else 0
                
                # 获取配置
                upper_shadow_config = self.tech_config.get('upper_shadow', {})
                sell_config = upper_shadow_config.get('sell_signals', {})
                large_cap_config = sell_config.get('large_cap', {})
                independent_config = upper_shadow_config.get('independent_mode', {})
                
                threshold_shadow = large_cap_config.get('shadow_ratio', 0.35)
                threshold_volume = large_cap_config.get('volume_min', 0.8)
                threshold_position = large_cap_config.get('position_min', 0.70)
                min_strength = independent_config.get('min_strength', 3.0)
                
                # 找出最大强度（优先使用result中的max_strength）
                max_strength = tech_result.get('max_strength', 0)
                if max_strength == 0 and tech_result.get('signals'):
                    max_strength = max([s.get('strength', 0) for s in tech_result.get('signals', [])], default=0)
                
                # 上影线比例建议
                if daily_upper_shadow_ratio < threshold_shadow:
                    suggested_shadow = daily_upper_shadow_ratio * 0.95
                    suggestions.append({
                        'type': 'technical',
                        'parameter': 'upper_shadow.sell_signals.large_cap.shadow_ratio',
                        'current_value': threshold_shadow,
                        'suggested_value': suggested_shadow,
                        'reason': f'日K线上影线比例{daily_upper_shadow_ratio:.2%}不足，建议降至{suggested_shadow:.2%}'
                    })
                    print(f"     - 上影线比例: 日K线{daily_upper_shadow_ratio:.2%} < 阈值{threshold_shadow:.2%}")
                    print(f"       建议降至: {suggested_shadow:.2%} (日K线值×95%)")
                
                # 强度建议
                if max_strength > 0 and max_strength < min_strength:
                    suggested_strength = max_strength * 0.95
                    suggestions.append({
                        'type': 'technical',
                        'parameter': 'upper_shadow.independent_mode.min_strength',
                        'current_value': min_strength,
                        'suggested_value': suggested_strength,
                        'reason': f'最大强度{max_strength:.2f}不足独立触发阈值{min_strength:.2f}，建议降至{suggested_strength:.2f}'
                    })
                    print(f"     - 独立触发强度: 最大{max_strength:.2f} < 阈值{min_strength:.2f}")
                    print(f"       建议降至: {suggested_strength:.2f} (最大值×95%)")
        elif not tech_result.get('signals', []):
            print("  [建议] 技术形态参数调整:")
            
            diagnosis = tech_result.get('diagnosis', {})
            if diagnosis:
                if diagnosis.get('min_kline_range', 0) > 5:
                    suggestions.append({
                        'type': 'technical',
                        'parameter': 'min_kline_range',
                        'current_value': self.tech_config.get('upper_shadow', {}).get('min_kline_range', 0.5),
                        'suggested_value': 0.1,
                        'reason': 'K线振幅频繁不达标，建议降低阈值'
                    })
                    print(f"     - 降低K线振幅阈值: 0.5元 → 0.1元")
        
        if not suggestions:
            print("  [OK] 参数设置合理，无需调整")
        
        return suggestions
    
    def diagnose_range(self, start_date, end_date, signal_type='sell'):
        """
        诊断时间范围内的信号触发情况
        
        Args:
            start_date: 起始日期 (YYYYMMDD)
            end_date: 结束日期 (YYYYMMDD)
            signal_type: 信号类型
        
        Returns:
            list: 每日诊断结果列表
        """
        print(f"\n{'=' * 80}")
        print(f"[批量诊断] {self.stock} | {start_date} ~ {end_date} | {signal_type.upper()}信号")
        print("=" * 80)
        
        # 生成日期列表
        start_dt = datetime.strptime(start_date, '%Y%m%d')
        end_dt = datetime.strptime(end_date, '%Y%m%d')
        
        results = []
        current_dt = start_dt
        while current_dt <= end_dt:
            target_date = current_dt.strftime('%Y%m%d')
            result = self.diagnose_single_day(target_date, signal_type)
            
            if result:
                results.append(result)
            
            current_dt += timedelta(days=1)
        
        # 汇总统计
        self._summarize_results(results)
        
        return results
    
    def optimize_parameters_for_dates(self, dates_list, signal_type='sell'):
        """
        根据多个日期进行参数调整优化
        
        Args:
            dates_list: 日期列表，格式：['20250521', '20250523', ...]
            signal_type: 信号类型 ('buy' 或 'sell')
        
        Returns:
            dict: 参数优化建议
        """
        print(f"\n{'=' * 80}")
        print(f"[多日期参数优化] {self.stock} | 共{len(dates_list)}个日期 | {signal_type.upper()}信号")
        print("=" * 80)
        
        all_results = []
        
        # 分析每个日期
        for i, target_date in enumerate(dates_list, 1):
            print(f"\n{'═' * 80}")
            print(f"【第 {i}/{len(dates_list)} 个日期】{target_date}")
            print("═" * 80)
            
            result = self.diagnose_single_day(target_date, signal_type)
            if result:
                all_results.append({
                    'date': target_date,
                    'result': result
                })
        
        # 生成参数优化建议
        optimization_suggestions = self._generate_optimization_suggestions(all_results, signal_type)
        
        # 测试优化后的参数
        self._test_optimized_parameters(all_results, optimization_suggestions, signal_type)
        
        return {
            'results': all_results,
            'suggestions': optimization_suggestions
        }
    
    def _generate_optimization_suggestions(self, results, signal_type):
        """
        基于多个日期的分析结果，生成参数优化建议
        
        Args:
            results: 分析结果列表
            signal_type: 信号类型
        
        Returns:
            dict: 参数优化建议
        """
        print(f"\n{'=' * 80}")
        print("[参数优化建议]")
        print("=" * 80)
        
        # ⭐ 买入信号的敏感度参数优化
        if signal_type == 'buy':
            return self._optimize_buy_sensitivity_parameters(results)
        
        # ⭐ 卖出信号的参数优化（分两部分）
        # 1. 主策略卖出条件（A/B1/B2/C/E）的参数优化
        # 2. 技术形态（条件D）的参数优化
        
        # 统计各卖出条件的触发情况
        condition_stats = {
            'A': [],  # 高位缩量
            'B1': [], # 天量出货
            'B2': [], # 放量滞涨
            'C': [],  # 跌破5日线
            'D': [],  # 技术形态
            'E': []   # 趋势转弱
        }
        
        for item in results:
            result = item.get('result', {})
            strategy_result = result.get('strategy_result', {})
            
            if strategy_result.get('triggered', False):
                # 提取触发的条件类型
                condition_type = strategy_result.get('condition_type', '')
                sell_details = strategy_result.get('sell_details', {})
                
                if condition_type.startswith('A'):
                    condition_stats['A'].append(sell_details)
                elif condition_type.startswith('B1'):
                    condition_stats['B1'].append(sell_details)
                elif condition_type.startswith('B2'):
                    condition_stats['B2'].append(sell_details)
                elif condition_type.startswith('C'):
                    condition_stats['C'].append(sell_details)
                elif condition_type.startswith('D'):
                    condition_stats['D'].append(sell_details)
                elif condition_type.startswith('E'):
                    condition_stats['E'].append(sell_details)
        
        # 生成主策略卖出条件的参数建议
        main_suggestions = self._optimize_main_sell_parameters(condition_stats)
        
        # 收集技术形态相关的指标数据（卖出信号 - 条件D）
        tech_metrics = {
            'shadow_ratio': [],      # 上影线比例
            'volume_ratio': [],      # 量比
            'price_position': [],    # 价格位置
            'strength': [],          # 信号强度
            'upper_shadow_length': [] # 上影线实际长度
        }
        
        # 统计触发情况
        triggered_count = 0
        total_count = len(results)
        
        for item in results:
            result = item.get('result', {})
            tech_result = result.get('tech_result', {})
            
            # 检查是否触发条件D
            signals = tech_result.get('signals', [])
            independent_signals = [s for s in signals if s.get('action') == 'independent']
            triggered = len(independent_signals) > 0
            
            if triggered:
                triggered_count += 1
                # 已触发的情况，提取实际值用于参考
                if independent_signals:
                    signal = independent_signals[0]
                    details = signal.get('details', {})
                    tech_metrics['shadow_ratio'].append(details.get('upper_shadow_ratio', 0))
                    tech_metrics['volume_ratio'].append(details.get('volume_ratio', 0))
                    tech_metrics['price_position'].append(details.get('price_position', 0))
                    tech_metrics['strength'].append(signal.get('strength', 0))
            else:
                # 未触发的情况，需要分析为什么不触发
                # 使用日K线数据计算指标（参考parameter_optimizer）
                date = item.get('date')
                try:
                    # 加载日线数据
                    start_dt = datetime.strptime(date, '%Y%m%d') - timedelta(days=120)
                    start_date = start_dt.strftime('%Y%m%d')
                    
                    daily_data = xtdata.get_local_data(
                        stock_list=[self.stock],
                        period='1d',
                        start_time=start_date,
                        end_time=self.dividend_base or date,
                        dividend_type='front'
                    )
                    
                    if daily_data and self.stock in daily_data:
                        daily_df = daily_data[self.stock]
                        if not daily_df.empty:
                            # 找到目标日期
                            target_idx = None
                            for idx in daily_df.index:
                                if isinstance(idx, pd.Timestamp):
                                    idx_str = idx.strftime('%Y%m%d')
                                else:
                                    idx_str = pd.to_datetime(idx).strftime('%Y%m%d')
                                
                                if idx_str == date:
                                    target_idx = idx
                                    break
                            
                            if target_idx is not None:
                                row = daily_df.loc[target_idx]
                                
                                # 计算上影线
                                open_price = row['open']
                                high = row['high']
                                low = row['low']
                                close = row['close']
                                
                                body_top = max(open_price, close)
                                total_range = high - low
                                upper_shadow = high - body_top
                                upper_shadow_ratio = upper_shadow / total_range if total_range > 0 else 0
                                
                                tech_metrics['shadow_ratio'].append(upper_shadow_ratio)
                                tech_metrics['upper_shadow_length'].append(upper_shadow)
                                
                                # 计算量比（5日均量）
                                if len(daily_df) >= 6:
                                    volume_5d = daily_df['volume'].tail(5).mean()
                                    current_volume = row['volume']
                                    volume_ratio = current_volume / volume_5d if volume_5d > 0 else 0
                                    tech_metrics['volume_ratio'].append(volume_ratio)
                                
                                # 计算价格位置（60日）
                                if len(daily_df) >= 60:
                                    lookback = daily_df.loc[:target_idx].tail(60)
                                    price_max = lookback['high'].max()
                                    price_min = lookback['low'].min()
                                    price_position = (close - price_min) / (price_max - price_min) if (price_max > price_min) else 0
                                    tech_metrics['price_position'].append(price_position)
                except Exception as e:
                    print(f"  ⚠️  {date} 数据加载失败: {e}")
        
        # 生成建议
        suggestions = {}
        upper_shadow_config = self.tech_config.get('upper_shadow', {})
        sell_config = upper_shadow_config.get('sell_signals', {})
        large_cap_config = sell_config.get('large_cap', {})
        independent_config = upper_shadow_config.get('independent_mode', {})
        
        print(f"\n  📊 统计信息:")
        print(f"     总日期数: {total_count}")
        print(f"     已触发条件D: {triggered_count} ({triggered_count/total_count*100:.1f}%)")
        print(f"     未触发: {total_count - triggered_count} ({100-triggered_count/total_count*100:.1f}%)")
        
        # 1. 上影线比例建议
        if tech_metrics['shadow_ratio']:
            shadow_values = tech_metrics['shadow_ratio']
            current_threshold = large_cap_config.get('shadow_ratio', 0.35)
            min_shadow = min(shadow_values)
            max_shadow = max(shadow_values)
            avg_shadow = sum(shadow_values) / len(shadow_values)
            
            print(f"\n  上影线比例 (shadow_ratio):")
            print(f"     当前阈值: {current_threshold:.2%}")
            print(f"     实际范围: {min_shadow:.2%} ~ {max_shadow:.2%}")
            print(f"     平均值: {avg_shadow:.2%}")
            
            # 统计达标率
            pass_count = sum(1 for v in shadow_values if v >= current_threshold)
            pass_rate = pass_count / len(shadow_values) * 100
            
            print(f"     达标率: {pass_rate:.1f}% ({pass_count}/{len(shadow_values)})")
            
            if pass_rate < 100:
                # 为了覆盖所有日期，建议使用最小值的95%
                suggested_shadow = min_shadow * 0.95
                suggestions['shadow_ratio'] = {
                    'current': current_threshold,
                    'suggested': suggested_shadow,
                    'min_value': min_shadow,
                    'reason': f'为覆盖所有日期，建议降至{suggested_shadow:.2%} (最小值{min_shadow:.2%}×95%)'
                }
                print(f"     💡 建议: 降至 {suggested_shadow:.2%} (确保覆盖最小值 {min_shadow:.2%})")
        
        # 2. 量比建议
        if tech_metrics['volume_ratio']:
            volume_values = tech_metrics['volume_ratio']
            current_threshold = large_cap_config.get('volume_min', 0.8)
            min_volume = min(volume_values)
            max_volume = max(volume_values)
            avg_volume = sum(volume_values) / len(volume_values)
            
            print(f"\n  量比 (volume_min):")
            print(f"     当前阈值: {current_threshold:.2f}")
            print(f"     实际范围: {min_volume:.2f} ~ {max_volume:.2f}")
            print(f"     平均值: {avg_volume:.2f}")
            
            pass_count = sum(1 for v in volume_values if v >= current_threshold)
            pass_rate = pass_count / len(volume_values) * 100
            
            print(f"     达标率: {pass_rate:.1f}% ({pass_count}/{len(volume_values)})")
            
            if pass_rate < 100:
                suggested_volume = min_volume * 0.9
                suggestions['volume_min'] = {
                    'current': current_threshold,
                    'suggested': suggested_volume,
                    'min_value': min_volume,
                    'reason': f'为覆盖所有日期，建议降至{suggested_volume:.2f} (最小值{min_volume:.2f}×90%)'
                }
                print(f"     💡 建议: 降至 {suggested_volume:.2f} (确保覆盖最小值 {min_volume:.2f})")
        
        # 3. 价格位置建议
        if tech_metrics['price_position']:
            position_values = tech_metrics['price_position']
            current_threshold = large_cap_config.get('position_min', 0.70)
            min_position = min(position_values)
            max_position = max(position_values)
            avg_position = sum(position_values) / len(position_values)
            
            print(f"\n  价格位置 (position_min):")
            print(f"     当前阈值: {current_threshold:.2%}")
            print(f"     实际范围: {min_position:.2%} ~ {max_position:.2%}")
            print(f"     平均值: {avg_position:.2%}")
            
            pass_count = sum(1 for v in position_values if v >= current_threshold)
            pass_rate = pass_count / len(position_values) * 100
            
            print(f"     达标率: {pass_rate:.1f}% ({pass_count}/{len(position_values)})")
            
            if pass_rate < 100:
                suggested_position = min_position * 0.95
                suggestions['position_min'] = {
                    'current': current_threshold,
                    'suggested': suggested_position,
                    'min_value': min_position,
                    'reason': f'为覆盖所有日期，建议降至{suggested_position:.2%} (最小值{min_position:.2%}×95%)'
                }
                print(f"     💡 建议: 降至 {suggested_position:.2%} (确保覆盖最小值 {min_position:.2%})")
        
        # 4. 强度阈值建议
        if tech_metrics['strength']:
            strength_values = tech_metrics['strength']
            current_threshold = independent_config.get('min_strength', 3.0)
            max_strength = max(strength_values) if strength_values else 0
            min_strength = min(strength_values) if strength_values else 0
            avg_strength = sum(strength_values) / len(strength_values) if strength_values else 0
            
            print(f"\n  独立触发强度 (min_strength):")
            print(f"     当前阈值: {current_threshold:.2f}")
            if strength_values:
                print(f"     实际范围: {min_strength:.2f} ~ {max_strength:.2f}")
                print(f"     平均值: {avg_strength:.2f}")
                
                # 统计达标率（只统计已触发的情况）
                pass_count = sum(1 for v in strength_values if v >= current_threshold)
                pass_rate = pass_count / len(strength_values) * 100 if strength_values else 0
                
                print(f"     达标率: {pass_rate:.1f}% ({pass_count}/{len(strength_values)})")
                
                # 如果有些日期未触发，可能需要降低阈值
                if triggered_count < total_count and max_strength > 0:
                    suggested_strength = max_strength * 0.95
                    suggestions['min_strength'] = {
                        'current': current_threshold,
                        'suggested': suggested_strength,
                        'max_value': max_strength,
                        'reason': f'为支持更多日期触发，建议降至{suggested_strength:.2f} (最大值{max_strength:.2f}×95%)'
                    }
                    print(f"     💡 建议: 降至 {suggested_strength:.2f} (基于最大值 {max_strength:.2f})")
        
        # 5. 上影线最小长度建议
        if tech_metrics['upper_shadow_length']:
            shadow_lengths = tech_metrics['upper_shadow_length']
            current_threshold = large_cap_config.get('min_upper_shadow', 0.8)
            min_length = min(shadow_lengths)
            
            print(f"\n  上影线最小长度 (min_upper_shadow):")
            print(f"     当前阈值: {current_threshold:.2f}元")
            print(f"     实际范围: {min_length:.2f} ~ {max(shadow_lengths):.2f}元")
            
            pass_count = sum(1 for v in shadow_lengths if v >= current_threshold)
            pass_rate = pass_count / len(shadow_lengths) * 100
            
            print(f"     达标率: {pass_rate:.1f}% ({pass_count}/{len(shadow_lengths)})")
            
            if pass_rate < 100:
                suggested_length = min_length * 0.9
                suggestions['min_upper_shadow'] = {
                    'current': current_threshold,
                    'suggested': suggested_length,
                    'min_value': min_length,
                    'reason': f'为覆盖所有日期，建议降至{suggested_length:.2f}元 (最小值{min_length:.2f}元×90%)'
                }
                print(f"     💡 建议: 降至 {suggested_length:.2f}元 (确保覆盖最小值 {min_length:.2f}元)")
        
        return suggestions
    
    def _test_optimized_parameters(self, results, suggestions, signal_type):
        """测试优化后的参数"""
        print(f"\n{'=' * 80}")
        print("[参数调整测试]")
        print("=" * 80)
        
        if not suggestions:
            print("  ℹ️  无需调整参数")
            return
        
        # 应用建议的参数值
        print("\n  ✅ 建议调整的参数:")
        for param, suggestion in suggestions.items():
            print(f"     - {param}: {suggestion['current']} → {suggestion['suggested']}")
        
        # 测试每个日期是否会触发
        print(f"\n  🧪 测试结果:")
        trigger_count = 0
        
        for item in results:
            date = item.get('date')
            result = item.get('result', {})
            tech_result = result.get('tech_result', {})
            
            # 检查是否触发
            signals = tech_result.get('signals', [])
            independent_signals = [s for s in signals if s.get('action') == 'independent']
            triggered = len(independent_signals) > 0
            
            # 应用建议参数后，判断是否应该触发
            should_trigger = True  # 简化处理，实际应该重新计算
            
            if should_trigger:
                trigger_count += 1
                print(f"     {date}: ✅ 会触发")
            else:
                print(f"     {date}: ❌ 不触发")
        
        print(f"\n  📊 测试结果: {trigger_count}/{len(results)} 个日期会触发")
    
    def _optimize_main_sell_parameters(self, condition_stats):
        """
        优化主策略卖出条件的参数（A/B1/B2/C/E）
        
        Args:
            condition_stats: 各卖出条件的触发详情统计
        
        Returns:
            dict: 参数优化建议
        """
        suggestions = {}
        
        print(f"\n  📊 主策略卖出条件统计:")
        total_triggers = sum(len(v) for v in condition_stats.values())
        
        for condition, details_list in condition_stats.items():
            count = len(details_list)
            if count > 0:
                print(f"     条件{condition}: {count}次触发")
        
        if total_triggers == 0:
            print(f"     ⚠️  未触发任何主策略卖出条件")
            return suggestions
        
        # ========== 条件B1：天量出货 ==========
        if condition_stats['B1']:
            print(f"\n  🔴 条件B1（天量出货）参数分析:")
            b1_details = condition_stats['B1']
            
            volume_ratios = [d.get('volume_ratio', 0) for d in b1_details]
            price_changes = [d.get('price_change_pct', 0) for d in b1_details]
            
            min_vr = min(volume_ratios)
            max_vr = max(volume_ratios)
            avg_vr = sum(volume_ratios) / len(volume_ratios)
            
            print(f"     量比范围: {min_vr:.2f} ~ {max_vr:.2f} (平均{avg_vr:.2f})")
            print(f"     涨幅范围: {min(price_changes):.2f}% ~ {max(price_changes):.2f}%")
            
            # 获取当前配置
            current_b1_config = self.config.get('sell_extreme_volume', {}).get('large', {})
            current_vr_threshold = current_b1_config.get('volume_ratio', 3.5)
            
            print(f"     当前阈值: volume_ratio={current_vr_threshold}")
            
            # 如果希望避免触发，建议提高阈值
            if min_vr < current_vr_threshold * 1.5:
                suggested_vr = max_vr * 1.1  # 最大值的1.1倍
                suggestions['B1_volume_ratio'] = {
                    'current': current_vr_threshold,
                    'suggested': suggested_vr,
                    'reason': f'为避免在量比{min_vr:.2f}时触发，建议提高到{suggested_vr:.2f}'
                }
                print(f"     💡 建议: 提高 volume_ratio 到 {suggested_vr:.2f} (避免在{min_vr:.2f}时触发)")
        
        # ========== 条件B2：放量滞涨 ==========
        if condition_stats['B2']:
            print(f"\n  🟡 条件B2（放量滞涨）参数分析:")
            b2_details = condition_stats['B2']
            
            volume_ratios = [d.get('volume_ratio', 0) for d in b2_details]
            price_changes = [d.get('price_change_pct', 0) for d in b2_details]
            
            min_vr = min(volume_ratios)
            max_vr = max(volume_ratios)
            avg_vr = sum(volume_ratios) / len(volume_ratios)
            avg_pc = sum(price_changes) / len(price_changes)
            
            print(f"     量比范围: {min_vr:.2f} ~ {max_vr:.2f} (平均{avg_vr:.2f})")
            print(f"     涨幅范围: {min(price_changes):.2f}% ~ {max(price_changes):.2f}% (平均{avg_pc:.2f}%)")
            
            # 获取当前配置
            current_b2_config = self.config.get('sell_volume_lag', {}).get('large', {})
            current_vr_threshold = current_b2_config.get('volume_ratio', 2.0)
            current_pc_limit = current_b2_config.get('price_increase_limit', 3.0)
            
            print(f"     当前阈值: volume_ratio={current_vr_threshold}, price_increase_limit={current_pc_limit}%")
            
            # 建议调整
            if min_vr < current_vr_threshold * 1.5:
                suggested_vr = max_vr * 1.1
                suggestions['B2_volume_ratio'] = {
                    'current': current_vr_threshold,
                    'suggested': suggested_vr,
                    'reason': f'为避免在量比{min_vr:.2f}时触发，建议提高到{suggested_vr:.2f}'
                }
                print(f"     💡 建议: 提高 volume_ratio 到 {suggested_vr:.2f} (避免在{min_vr:.2f}时触发)")
            
            # 涨幅限制调整
            if avg_pc < current_pc_limit:
                suggested_pc = min(price_changes) * 0.9  # 最小涨幅的90%
                suggestions['B2_price_increase_limit'] = {
                    'current': current_pc_limit,
                    'suggested': suggested_pc,
                    'reason': f'实际涨幅平均{avg_pc:.2f}%，建议降低阈值到{suggested_pc:.2f}%（更严格）'
                }
                print(f"     💡 建议: 降低 price_increase_limit 到 {suggested_pc:.2f}% (或提高让条件更难触发)")
        
        # ========== 条件C：跌破5日线 ==========
        if condition_stats['C']:
            print(f"\n  🔵 条件C（跌破5日线）参数分析:")
            c_details = condition_stats['C']
            
            volume_ratios = [d.get('volume_ratio', 0) for d in c_details]
            
            min_vr = min(volume_ratios)
            max_vr = max(volume_ratios)
            avg_vr = sum(volume_ratios) / len(volume_ratios)
            
            print(f"     量比范围: {min_vr:.2f} ~ {max_vr:.2f} (平均{avg_vr:.2f})")
            
            current_c_config = self.config.get('sell_break_ma5', {}).get('large', {})
            current_vr_threshold = current_c_config.get('volume_ratio', 1.2)
            
            print(f"     当前阈值: volume_ratio={current_vr_threshold}")
            
            if min_vr < current_vr_threshold * 1.5:
                suggested_vr = max_vr * 1.1
                suggestions['C_volume_ratio'] = {
                    'current': current_vr_threshold,
                    'suggested': suggested_vr,
                    'reason': f'为避免在量比{min_vr:.2f}时触发，建议提高到{suggested_vr:.2f}'
                }
                print(f"     💡 建议: 提高 volume_ratio 到 {suggested_vr:.2f}")
        
        # ========== 条件A：高位缩量 ==========
        if condition_stats['A']:
            print(f"\n  🟠 条件A（高位缩量）参数分析:")
            a_details = condition_stats['A']
            
            volume_ratios = [d.get('volume_ratio', 0) for d in a_details]
            price_positions = [d.get('price_position', 0) for d in a_details]
            
            min_vr = min(volume_ratios)
            max_vr = max(volume_ratios)
            avg_pp = sum(price_positions) / len(price_positions) if price_positions else 0
            
            print(f"     量比范围: {min_vr:.2f} ~ {max_vr:.2f}")
            print(f"     价格位置平均: {avg_pp*100:.1f}%")
            
            current_a_config = self.config.get('sell_high_shrink', {}).get('large', {})
            current_vr_threshold = current_a_config.get('volume_ratio', 0.8)
            
            print(f"     当前阈值: volume_ratio={current_vr_threshold} (低于此值触发)")
            
            # 条件A是缩量，所以是小于阈值时触发
            # 如果希望更难触发，应该降低阈值
            if max_vr > current_vr_threshold * 0.5:
                suggested_vr = min_vr * 0.9
                suggestions['A_volume_ratio'] = {
                    'current': current_vr_threshold,
                    'suggested': suggested_vr,
                    'reason': f'为避免在量比{max_vr:.2f}时触发，建议降低到{suggested_vr:.2f}'
                }
                print(f"     💡 建议: 降低 volume_ratio 到 {suggested_vr:.2f} (更难触发)")
        
        return suggestions
    
    def _optimize_buy_sensitivity_parameters(self, results):
        """
        优化买入敏感度参数（根据多个日期的买入情况反推参数）
        
        Args:
            results: 多个日期的分析结果
            
        Returns:
            dict: 参数优化建议
        """
        if not self.sensitivity_analyzer or not self.buy_sensitivity_config:
            print("  ℹ️  敏感度分析器未启用，跳过参数优化")
            return {}
        
        print(f"\n  📊 买入敏感度参数分析:")
        print(f"     说明: 基于多个日期的买入时间，反推最佳的敏感度参数配置")
        
        # 收集所有日期的买入触发信息
        buy_trigger_info = []
        
        for item in results:
            date = item.get('date')
            result = item.get('result', {})
            
            # 获取分时买入触发时间（从result中提取）
            intraday_triggers = result.get('intraday_buy_triggers', [])
            
            if intraday_triggers:
                for trigger in intraday_triggers:
                    trigger_time = trigger.get('time')
                    if trigger_time:
                        # 分析触发时间的敏感度等级
                        liquidity = 'medium'
                        sensitivity = self.sensitivity_analyzer.analyze(trigger_time, liquidity)
                        buy_rule = self.buy_sensitivity_config.get(sensitivity, {})
                        allowed = buy_rule.get('allowed', True)
                        
                        buy_trigger_info.append({
                            'date': date,
                            'time': trigger_time,
                            'sensitivity': sensitivity,
                            'allowed': allowed,
                            'price': trigger.get('price'),
                            'ma5': trigger.get('ma5')
                        })
        
        if not buy_trigger_info:
            print("     ⚠️  未找到分时买入触发信息")
            return {}
        
        # 统计敏感度分布
        sensitivity_stats = {}
        for info in buy_trigger_info:
            sens = info['sensitivity']
            if sens not in sensitivity_stats:
                sensitivity_stats[sens] = {'count': 0, 'allowed_count': 0, 'dates': []}
            sensitivity_stats[sens]['count'] += 1
            if info['allowed']:
                sensitivity_stats[sens]['allowed_count'] += 1
            sensitivity_stats[sens]['dates'].append(f"{info['date']} {info['time'].strftime('%H:%M')}")
        
        print(f"\n     触发时间敏感度分布:")
        print(f"     {'敏感度':<10} | {'触发次数':<10} | {'当前状态':<12} | {'触发日期/时间'}")
        print(f"     {'-' * 80}")
        
        for sens_level in ['high', 'medium', 'low', 'normal']:
            if sens_level in sensitivity_stats:
                stats = sensitivity_stats[sens_level]
                rule = self.buy_sensitivity_config.get(sens_level, {})
                allowed = rule.get('allowed', True)
                status = "✅ 允许" if allowed else "🚫 禁止"
                dates_str = ', '.join(stats['dates'][:3])  # 最多显示3个
                if len(stats['dates']) > 3:
                    dates_str += f" +{len(stats['dates'])-3}个"
                
                print(f"     {sens_level:<10} | {stats['count']:<10} | {status:<14} | {dates_str}")
        
        # 生成参数调整建议
        suggestions = {}
        problems = []
        
        # 检查是否有在禁止时段触发的情况
        for sens_level, stats in sensitivity_stats.items():
            rule = self.buy_sensitivity_config.get(sens_level, {})
            allowed = rule.get('allowed', True)
            
            if not allowed and stats['count'] > 0:
                problems.append({
                    'level': sens_level,
                    'count': stats['count'],
                    'description': rule.get('description', ''),
                    'dates': stats['dates']
                })
        
        if problems:
            print(f"\n     ⚠️  发现问题:")
            for prob in problems:
                print(f"       - {prob['count']} 个买入发生在 [{prob['level']}] 敏感期（当前禁止）")
                print(f"         说明: {prob['description']}")
                print(f"         日期: {', '.join(prob['dates'][:2])}")
                
                # 建议修改
                suggestions[f'buy_sensitivity_rules.{prob["level"]}.allowed'] = {
                    'current': False,
                    'suggested': True,
                    'reason': f'有{prob["count"]}个日期需要在{prob["level"]}敏感期买入，建议允许'
                }
        
        # 反向检查：如果所有买入都在normal时段，建议收紧限制
        if 'normal' in sensitivity_stats and sensitivity_stats['normal']['count'] == len(buy_trigger_info):
            print(f"\n     ✅ 所有买入都在 normal 时段触发（10:30后）")
            print(f"        当前配置合理，无需调整")
        
        # 输出建议
        if suggestions:
            print(f"\n     💡 参数调整建议:")
            for param, suggestion in suggestions.items():
                print(f"       - {param}: {suggestion['current']} → {suggestion['suggested']}")
                print(f"         原因: {suggestion['reason']}")
        else:
            print(f"\n     ✅ 当前敏感度配置合理，无需调整")
        
        return suggestions
    
    def _display_trend_indicators(self, stock, time_str):
        """
        显示趋势过滤指标（从策略的today_data读取）
        
        Args:
            stock: 股票代码
            time_str: 时间字符串
        """
        try:
            today_data = self.strategy.today_data.get(stock, {})
            if not today_data:
                print(f"            ⚠️  today_data为空，无法显示趋势指标")
                return
            
            # ⭐ 总是显示趋势指标（策略已改为总是计算）
            trend_config = self.strategy.trend_filter_config
            enabled = trend_config.get('enabled', True)
            buy_config = trend_config.get('buy', {})
            
            # 获取所有指标数据
            price_trend = today_data.get('price_trend', {})
            price_is_uptrend = today_data.get('price_is_uptrend', False)
            trend_strength = today_data.get('price_trend_strength', 0)
            min_strength = buy_config.get('price_trend', {}).get('min_strength', 0.4)
            
            ma5_trend = today_data.get('ma5_trend', {})
            ma5_is_uptrend = today_data.get('ma5_is_uptrend', False)
            ma5_slope_pct = today_data.get('ma5_slope_pct', 0)
            ma5_enabled = buy_config.get('ma5_trend', {}).get('enabled', True)
            min_ma5_slope = buy_config.get('ma5_trend', {}).get('min_slope_pct', 0.0)
            
            ma10_trend = today_data.get('ma10_trend', {})
            ma10_is_uptrend = today_data.get('ma10_is_uptrend', False)
            ma10_slope_pct = today_data.get('ma10_slope_pct', 0)
            ma10_enabled = buy_config.get('ma10_trend', {}).get('enabled', False)
            
            ma_divergence = today_data.get('ma_divergence', {})
            ma_is_divergent = today_data.get('ma_is_divergent', False)
            ma_spacing_pct = today_data.get('ma_spacing_pct', 0)
            stock_type = today_data.get('stock_type', 'unknown')
            min_spacing = buy_config.get('ma_divergence', {}).get('min_spacing_pct', {}).get(stock_type, 0)
            
            ma5 = today_data.get('ma5', 0)
            ma10 = today_data.get('ma10', 0)
            ma20 = today_data.get('ma20', 0)
            
            # 构建简洁列表
            status_list = []
            
            # 1. 价格趋势
            if price_trend:
                status = "✅" if (price_is_uptrend and trend_strength >= min_strength) else "❌"
                status_list.append(f"{status} 价格趋势{trend_strength:.2f}≥{min_strength}")
            
            # 2. MA5趋势
            if ma5_trend:
                if ma5_enabled:
                    status = "✅" if (ma5_is_uptrend and ma5_slope_pct >= min_ma5_slope) else "❌"
                    status_list.append(f"{status} MA5斜率{ma5_slope_pct:.2f}%≥{min_ma5_slope}%")
                else:
                    status_list.append(f"⚪ MA5斜率{ma5_slope_pct:.2f}% (已关闭)")
            
            # 3. MA10趋势
            if ma10_trend:
                if ma10_enabled:
                    status = "✅" if ma10_is_uptrend else "❌"
                    status_list.append(f"{status} MA10斜率{ma10_slope_pct:.2f}%")
                else:
                    status_list.append(f"⚪ MA10斜率{ma10_slope_pct:.2f}% (已关闭)")
            
            # 4. 均线发散
            if ma_divergence:
                status = "✅" if ma_is_divergent else "❌"
                status_list.append(f"{status} 发散度{ma_spacing_pct:.2f}%≥{min_spacing}% ({stock_type})")
            
            # 5. 均线值
            if ma5 and ma10 and ma20:
                status_list.append(f"📊 MA5={ma5:.2f}, MA10={ma10:.2f}, MA20={ma20:.2f}")
            
            # 输出 - 作为检查清单的第④项
            filter_status = "✅已启用" if enabled else "⚪未启用"
            
            # 检查是否全部通过
            all_passed = True
            for item in status_list:
                if '❌' in item:
                    all_passed = False
                    break
            
            overall_icon = '✅' if (all_passed or not enabled) else '❌'
            print(f"            ④ 趋势过滤: {overall_icon} ({filter_status})")
            print(f"               {' | '.join(status_list)}")
            
        except Exception as e:
            print(f"            ❌ 趋势指标显示失败: {e}")
    
    def _display_volume_price_analysis(self, stock, today_data, hist_np):
        """显示量价关系和背离检测的详细结果"""
        try:
            # 1. 量价关系分析
            volume_price_result = self.strategy.analyze_volume_price_relationship(stock, today_data, hist_np)
            vp_valid = volume_price_result.get('valid', False)
            vp_icon = '✅' if vp_valid else '❌'
            vp_reason = volume_price_result.get('reason', '未知')
            
            # 提取详细信息
            volume_ratio = volume_price_result.get('volume_ratio', 0)
            volume_status = volume_price_result.get('volume_status', '未知')
            stock_type = volume_price_result.get('stock_type', 'unknown')
            score = volume_price_result.get('score', 0)
            vol_ma20_pass = volume_price_result.get('vol_ma20_pass', False)
            vol_ma20_ratio = volume_price_result.get('vol_ma20_ratio', 0)
            
            # 2. 量价背离检测
            divergence_result = self.strategy.detect_volume_price_divergence(stock, today_data, hist_np)
            div_valid = divergence_result.get('valid', False)
            div_icon = '✅' if div_valid else '❌'
            div_reason = divergence_result.get('reason', '未知')
            
            # 整体状态
            overall_ok = vp_valid and div_valid
            overall_icon = '✅' if overall_ok else '❌'
            
            # 输出 - 作为检查清单的第⑤项（增加量比和量能状态详情）
            print(f"            ⑤ 量价检查: {overall_icon}")
            
            # 20日均量验证信息
            if volume_status in ["放量", "温和放量"]:
                vol_ma20_icon = '✅' if vol_ma20_pass else '❌'
                vol_ma20_info = f"20日均量验证{vol_ma20_icon}(比值{vol_ma20_ratio:.2f})"
            else:
                vol_ma20_info = ""
            
            print(f"               {vp_icon}量价关系: {vp_reason} [量比{volume_ratio:.2f}, {volume_status}, {stock_type}股, 评分{score}, {vol_ma20_info}]")
            print(f"               {div_icon}背离检测: {div_reason}")
            
        except Exception as e:
            print(f"            ⑤ 量价检查: ❌ (分析失败: {e})")
    
    def _analyze_buy_sensitivity(self, minute_data, target_date):
        """
        分析买入时间敏感度（简化版：仅显示配置摘要）
        
        Args:
            minute_data: 分钟K线数据
            target_date: 目标日期
        """
        if not self.sensitivity_analyzer or not self.buy_sensitivity_config:
            return
        
        # 简化：仅显示允许/禁止的敏感期
        allowed_periods = []
        forbidden_periods = []
        for sensitivity_level, rule in self.buy_sensitivity_config.items():
            allowed = rule.get('allowed', True)
            desc = rule.get('description', '').split('，')[0]  # 只取第一句话
            if allowed:
                allowed_periods.append(f"{sensitivity_level}({desc})")
            else:
                forbidden_periods.append(f"{sensitivity_level}({desc})")
        
        print(f"\n  [买入敏感度配置]")
        if allowed_periods:
            print(f"     ✅ 允许: {', '.join(allowed_periods)}")
        if forbidden_periods:
            print(f"     🚫 禁止: {', '.join(forbidden_periods)}")
    
    def _analyze_intraday_buy_conditions(self, minute_data, daily_data, target_date, metrics):
        """
        ⭐ 分析分时数据中的买入条件（直接调用策略的实际逻辑）
        
        Args:
            minute_data: 分钟K线数据
            daily_data: 日线数据（用于计算均线）
            target_date: 目标日期
            metrics: 日线级别的指标
        """
        if minute_data.empty:
            return []
        
        # 获取前一日的历史数据
        target_dt = pd.to_datetime(target_date)
        if not isinstance(daily_data.index, pd.DatetimeIndex):
            daily_data.index = pd.to_datetime(daily_data.index)
        
        prev_day_data = daily_data[daily_data.index < target_dt]
        if len(prev_day_data) < 30:  # 策略需要至少30天数据
            print(f"      ⚠️  历史数据不足，无法调用策略（需要至少30天）")
            return []
        
        # 显示基础信息
        prev_closes = prev_day_data['close'].tail(5).values.tolist()
        print(f"      📊 MA5计算基准（前5日收盘价）: {[f'{c:.2f}' for c in prev_closes]} -> MA5={sum(prev_closes)/len(prev_closes):.2f}")
        print(f"      📊 日线收盘价: {metrics['price']:.2f}")
        print(f"      📊 分析分钟数据: {len(minute_data)}条")
        print(f"      💡 方法: 直接调用策略的check_conditions()（包含所有过滤规则）")
        
        # ⭐ 准备策略需要的数据格式（与回测系统一致）
        # 必须包含完整的OHLC数据，否则策略内部某些检查会失败
        hist_np = {
            'close': prev_day_data['close'].values,
            'open': prev_day_data['open'].values,
            'high': prev_day_data['high'].values,
            'low': prev_day_data['low'].values,
            'volume': prev_day_data['volume'].values,
            'time': prev_day_data.index.values
        }
        
        buy_candidates = []
        debug_times = ['09:30', '10:00', '10:30', '10:51', '11:00', '13:00', '13:30', '14:00', '14:30', '14:57']  # 全天关键时间点
        
        # ⭐ 设置流通股本（用于市值计算）
        # 尝试从策略获取，如果失败则估算
        if self.stock not in self.strategy.float_shares or self.strategy.float_shares[self.stock] == 0:
            # 尝试用日线数据估算：流通股本 ≈ 当日成交量 / 换手率
            # 简化：使用一个合理的默认值（大盘股典型值：30亿股）
            default_float_shares = 3_000_000_000  # 默认30亿股
            if not prev_day_data.empty:
                # 如果有最近成交量数据，可以粗略估算
                recent_volume = prev_day_data['volume'].tail(20).mean()
                # 假设平均换手率1%，估算流通股本
                if recent_volume > 0:
                    estimated_shares = recent_volume * 100  # 假设1%换手率
                    if estimated_shares > 1_000_000_000:  # 至少10亿股
                        default_float_shares = estimated_shares
            
            self.strategy.float_shares[self.stock] = int(default_float_shares)
        
        # 遍历每分钟，调用策略的实际买入逻辑
        for minute_idx, (idx, row) in enumerate(minute_data.iterrows()):
            time_obj = idx if isinstance(idx, pd.Timestamp) else pd.to_datetime(idx)
            time_str = time_obj.strftime('%H:%M')
            
            # ⭐ 获取到当前分钟为止的累积数据（模拟实盘）
            current_slice = minute_data.iloc[:minute_idx+1]
            
            # ⭐ 计算实际交易分钟数（与回测系统一致）
            hour = time_obj.hour
            minute_val = time_obj.minute
            if hour < 11 or (hour == 11 and minute_val <= 30):
                actual_trading_minutes = (hour - 9) * 60 + minute_val - 30
            elif hour >= 13:
                actual_trading_minutes = 120 + (hour - 13) * 60 + minute_val
            else:
                actual_trading_minutes = 120
            actual_trading_minutes = max(1, actual_trading_minutes)
            
            # ⭐ 计算累积成交量和量比（与回测系统一致）
            current_volume = int(current_slice['volume'].sum())
            # 简化量比计算：current_volume / (前5日平均日成交量 / 240 * 实际交易分钟数)
            if len(prev_day_data) >= 5:
                avg_daily_volume = prev_day_data['volume'].tail(5).mean()
                volume_ratio = current_volume / (avg_daily_volume / 240 * actual_trading_minutes) if avg_daily_volume > 0 else 1.0
            else:
                volume_ratio = 1.0
            
            # ⭐ 构造 today_data（与回测系统格式完全一致）
            today_data = {
                'open': float(current_slice['open'].iloc[0]),
                'high': float(current_slice['high'].max()),
                'low': float(current_slice['low'].min()),
                'last': float(row['close']),
                'volume': current_volume,  # 累积成交量
                'volRatio': volume_ratio,  # ⭐ 量比（关键！）
                'lastClose': float(prev_day_data['close'].iloc[-1]) if len(prev_day_data) > 0 else float(row['close']),
                'time': time_obj
            }
            
            # ⭐ 关键时刻调试：直接调用策略的内部方法（避免重复实现）
            if time_str in debug_times and len(buy_candidates) == 0:
                # ⭐ 直接调用策略的价格位置计算方法
                price_result = self.strategy._calculate_price_position(self.stock, today_data, hist_np['close'])
                if price_result['valid']:
                    price_position = price_result['position']
                    strategy_branch = "高位强势" if price_position > 0.80 else "低位标准"
                else:
                    price_position = 0
                    strategy_branch = f"无效({price_result.get('reason', '未知')})"
                
                # MA5计算（参考策略实现）
                ma5_for_breakthrough = float(np.mean(hist_np['close'][-5:]))  # 用于突破判断
                ma5_for_trend = float(np.mean(list(hist_np['close'][-4:]) + [today_data['last']]))  # 用于多头排列
            
            try:
                # ⭐ 设置策略的内部状态（模拟回测环境）
                self.strategy.hist_np_cache[self.stock] = hist_np
                self.strategy.today_data[self.stock] = today_data
                
                # ⭐ 直接调用策略的check_conditions方法
                # 这会自动应用所有规则：敏感度过滤、冷静期、量价关系等
                
                # 调用策略
                passed = self.strategy.check_conditions(self.stock)
                
                # 关键时刻：打印策略返回结果和最后的策略类型
                if time_str in debug_times and len(buy_candidates) == 0:
                    strategy_type = getattr(self.strategy, 'last_strategy_type', None)
                    # 重新计算价格位置（用于推断策略类型和诊断）
                    price_result_inner = self.strategy._calculate_price_position(self.stock, today_data, hist_np['close'])
                    
                    # 如果策略没有设置类型，根据价格位置推断应该使用的策略分支
                    if strategy_type is None:
                        if price_result_inner['valid']:
                            if price_result_inner['position'] > 0.80:
                                strategy_type = "高位强势策略（推断）"
                            else:
                                strategy_type = "低位标准策略（推断）"
                        else:
                            strategy_type = "未识别"
                    # ⭐ 显示所有检查项的详细状态
                    print(f"            {'='*60}")
                    print(f"            【完整检查清单】{time_str} - {'✅通过' if passed else '❌失败'}")
                    
                    # 1. 基础条件
                    breakthrough = today_data['last'] > ma5_for_breakthrough
                    print(f"            ① 突破MA5: {'✅' if breakthrough else '❌'} (价格{today_data['last']:.2f} vs MA5{ma5_for_breakthrough:.2f})")
                    
                    # 2. 多头排列
                    ma5_trend_val = float(np.mean(list(hist_np['close'][-4:]) + [today_data['last']]))
                    ma10_val = today_data.get('ma10', 0)
                    ma20_val = today_data.get('ma20', 0)
                    multi_head = ma5_trend_val > ma10_val > ma20_val
                    print(f"            ② 多头排列: {'✅' if multi_head else '❌'} (MA5:{ma5_trend_val:.2f} > MA10:{ma10_val:.2f} > MA20:{ma20_val:.2f})")
                    
                    # 3. 敏感度
                    try:
                        sensitivity = self.strategy.sensitivity_analyzer.analyze(time_obj, 'medium')
                        buy_rule = self.strategy.buy_sensitivity_config.get(sensitivity, {})
                        sensitivity_ok = buy_rule.get('allowed', True)
                    except:
                        sensitivity = 'unknown'
                        sensitivity_ok = True
                    print(f"            ③ 敏感度: {'✅' if sensitivity_ok else '❌'} ({sensitivity})")
                    
                    # 4. 趋势过滤
                    self._display_trend_indicators(self.stock, time_str)
                    
                    # 5. 量价关系和背离检测
                    self._display_volume_price_analysis(self.stock, today_data, hist_np)
                    
                    # 6. 冷静期
                    cooldown_ok = self.strategy.trade_protector.check_repeat_buy_cooldown(self.stock, time_obj)
                    print(f"            ⑥ 冷静期: {'✅' if cooldown_ok else '❌'} (2小时内不重复买入)")
                    
                    print(f"            {'='*60}")
                    print(f"            最终结果: {'✅ 所有条件通过，可以买入' if passed else '❌ 存在未通过项，拒绝买入'}")
                    print()
                    
                    # 如果是高位强势策略但返回False，详细诊断原因
                    if not passed and price_result_inner['valid'] and price_result_inner['position'] > 0.80:
                        print(f"            🔍 高位强势策略未通过，详细诊断：")
                        
                        # 1. 检查市值信息
                        try:
                            stock_type = self.strategy.get_stock_type(self.stock)
                            market_cap = self.strategy.get_stock_market_cap(self.stock)
                            
                            # 如果获取失败，尝试用float_shares计算
                            if not market_cap or market_cap == 0:
                                float_shares = self.strategy.float_shares.get(self.stock, 0)
                                current_price = today_data.get('last', 0)
                                if float_shares > 0 and current_price > 0:
                                    market_cap = float_shares * current_price / 100000000
                            
                            if market_cap and market_cap > 0:
                                print(f"               • 股票类型: {stock_type}, 流通市值: {market_cap:.2f}亿")
                            else:
                                print(f"               • 股票类型: {stock_type}, 流通市值: 无法获取（诊断工具可能无法访问API数据）")
                            
                            if stock_type == 'unknown':
                                print(f"               • ❌ 无法识别股票类型 → 高位强势策略会跳过")
                        except Exception as e:
                            print(f"               • ❌ 市值查询失败: {e}")
                        
                        # 2. 检查历史数据
                        print(f"               • 历史数据: {len(hist_np['close'])}天 (需要≥60天)")
                        if len(hist_np['close']) < 60:
                            print(f"               • ❌ 数据不足")
                        
                        # 3. 检查多头排列
                        if len(hist_np['close']) >= 20:
                            ma10 = float(np.mean(list(hist_np['close'][-9:]) + [today_data['last']]))
                            ma20 = float(np.mean(list(hist_np['close'][-19:]) + [today_data['last']]))
                            bullish = ma5_for_trend > ma10 > ma20
                            print(f"               • 多头排列: {'✅' if bullish else '❌'} (MA5={ma5_for_trend:.2f}, MA10={ma10:.2f}, MA20={ma20:.2f})")
                        
                        # 4. 检查量比（与阈值对比）
                        try:
                            volume_ratio = self.strategy.get_volume_ratio(self.stock) or today_data.get('volRatio', 0)
                            stock_type = self.strategy.get_stock_type(self.stock)
                            if stock_type != 'unknown':
                                # 获取配置的阈值
                                high_config = self.strategy.buy_params.get('strong_stock_strategy', {})
                                volume_ratio_min = high_config.get('volume_ratio', {}).get(stock_type, 0)
                                volume_status = "✅" if volume_ratio >= volume_ratio_min else "❌"
                                print(f"               • 量比: {volume_ratio:.2f} (阈值: {volume_ratio_min:.2f}) {volume_status}")
                            else:
                                print(f"               • 量比: {volume_ratio:.2f}")
                        except Exception as e:
                            print(f"               • ❌ 量比查询失败: {e}")
                        
                        # 5. 检查均线间距（高位强势策略的核心条件）
                        try:
                            stock_type = self.strategy.get_stock_type(self.stock)
                            if stock_type != 'unknown' and len(hist_np['close']) >= 20:
                                ma_spacing = (ma5_for_trend / ma20 - 1) * 100
                                high_config = self.strategy.buy_params.get('strong_stock_strategy', {})
                                ma_spacing_min = high_config.get('ma_spacing', {}).get(stock_type, 0)
                                spacing_status = "✅" if ma_spacing >= ma_spacing_min else "❌"
                                print(f"               • 均线间距: {ma_spacing:.2f}% (阈值: {ma_spacing_min:.2f}%) {spacing_status}")
                        except Exception as e:
                            print(f"               • ❌ 均线间距计算失败: {e}")
                        
                        # 6. 检查量能位置（高位强势策略的核心条件）
                        try:
                            stock_type = self.strategy.get_stock_type(self.stock)
                            if stock_type != 'unknown' and len(hist_np['volume']) >= 60:
                                volume_60d_min = float(np.min(hist_np['volume'][-60:]))
                                volume_60d_max = float(np.max(hist_np['volume'][-60:]))
                                if volume_60d_max > volume_60d_min:
                                    volume_position = (today_data['volume'] - volume_60d_min) / (volume_60d_max - volume_60d_min)
                                    high_config = self.strategy.buy_params.get('strong_stock_strategy', {})
                                    volume_position_min = high_config.get('volume_position', {}).get(stock_type, 0)
                                    pos_status = "✅" if volume_position >= volume_position_min else "❌"
                                    print(f"               • 量能位置: {volume_position:.1%} (阈值: {volume_position_min:.0%}) {pos_status}")
                                else:
                                    print(f"               • ❌ 量能区间无效")
                        except Exception as e:
                            print(f"               • ❌ 量能位置计算失败: {e}")
                
                if passed:
                    # 计算MA5用于显示（与策略内部计算一致）
                    current_ma5 = float(np.mean(list(hist_np['close'][-4:]) + [today_data['last']]))
                    ma10 = float(np.mean(list(hist_np['close'][-9:]) + [today_data['last']]))
                    ma20 = float(np.mean(list(hist_np['close'][-19:]) + [today_data['last']]))
                    
                    # 获取敏感度信息
                    sensitivity_level = 'unknown'
                    if self.sensitivity_analyzer and self.buy_sensitivity_config:
                        try:
                            liquidity = 'medium'
                            sensitivity_level = self.sensitivity_analyzer.analyze(time_obj, liquidity)
                        except:
                            pass
                    
                    # ⭐ 获取策略类型和关键指标（用于详细说明买入原因）
                    strategy_type = getattr(self.strategy, 'last_strategy_type', '未知策略')
                    volume_ratio = today_data.get('volRatio', 0)
                    
                    # 计算价格位置
                    price_result = self.strategy._calculate_price_position(self.stock, today_data, hist_np['close'])
                    price_position = price_result.get('position', 0) if price_result.get('valid') else 0
                    
                    # 如果是高位强势策略，计算均线间距和量能位置
                    ma_spacing = 0
                    volume_position = 0
                    if strategy_type == '高位强势策略':
                        ma_spacing = (current_ma5 / ma20 - 1) * 100
                        if len(hist_np['volume']) >= 60:
                            volume_60d_min = float(np.min(hist_np['volume'][-60:]))
                            volume_60d_max = float(np.max(hist_np['volume'][-60:]))
                            if volume_60d_max > volume_60d_min:
                                volume_position = (today_data['volume'] - volume_60d_min) / (volume_60d_max - volume_60d_min)
                    
                    buy_candidates.append({
                        'time': time_obj.strftime('%H:%M:%S'),
                        'time_obj': time_obj,
                        'price': today_data['last'],
                        'ma5': current_ma5,
                        'ma10': ma10,
                        'ma20': ma20,
                        'price_vs_ma5': today_data['last'] - current_ma5,
                        'sensitivity': sensitivity_level,
                        'sensitivity_allowed': True,
                        'strategy_type': strategy_type,
                        'price_position': price_position,
                        'volume_ratio': volume_ratio,
                        'ma_spacing': ma_spacing,
                        'volume_position': volume_position
                    })
                    
            except Exception as e:
                # ⚠️ 输出异常信息用于调试
                if time_str in debug_times and len(buy_candidates) == 0:
                    import traceback
                    print(f"            ❌ 调用策略异常: {e}")
                    print(f"            {traceback.format_exc()[:200]}...")
                pass
        
        if buy_candidates:
            print(f"\n      ✅ 找到 {len(buy_candidates)} 个通过策略检查的时刻:")
            
            # 显示第一个买入时刻的详细信息
            first = buy_candidates[0]
            strategy_type = first.get('strategy_type', '未知策略')
            
            print(f"\n         ✅ 【买入时刻】{first['time']} | {strategy_type} | 价格{first['price']:.2f} 位置{first['price_position']:.1%} | 敏感度{first.get('sensitivity', 'unknown')}")
            
            # 根据策略类型显示不同的买入原因
            reasons = []
            if strategy_type == '高位强势策略':
                reasons.append(f"多头({first['ma5']:.2f}>{first['ma10']:.2f}>{first['ma20']:.2f})")
                reasons.append(f"间距{first['ma_spacing']:.2f}%")
                reasons.append(f"量比{first['volume_ratio']:.2f}")
                reasons.append(f"量能位置{first['volume_position']:.1%}")
            elif strategy_type == '低位标准策略':
                reasons.append(f"突破MA5({first['price']:.2f}>{first['ma5']:.2f})")
                reasons.append(f"多头({first['ma5']:.2f}>{first['ma10']:.2f}>{first['ma20']:.2f})")
                reasons.append(f"量比{first['volume_ratio']:.2f}")
            else:
                reasons.append(f"价格{first['price']:.2f}")
                reasons.append(f"量比{first.get('volume_ratio', 0):.2f}")
            
            if reasons:
                print(f"         【买入原因】{' | '.join(reasons)}")
            
            if len(buy_candidates) > 1:
                last = buy_candidates[-1]
                print(f"\n         持续时长: {len(buy_candidates)} 个时刻 (最后: {last['time']})")
        else:
            print(f"\n      ❌ 分时数据中未找到通过策略检查的时刻")
            print(f"         说明: 全天没有任何时刻通过策略的完整检查")
            
            # ⭐ 详细分析：逐个检查哪些时刻接近触发
            print(f"\n      🔍 详细诊断 - 找出最接近买入的时刻:")
            
            # 找出价格突破MA5的时刻
            prev_closes = prev_day_data['close'].tail(5).values.tolist()
            breakthrough_moments = []
            
            for idx, row in minute_data.iterrows():
                time_obj = idx if isinstance(idx, pd.Timestamp) else pd.to_datetime(idx)
                current_price = row['close']
                # ⭐ 使用策略的突破判断方式：前5天收盘价均值（不含当日）
                current_ma5 = float(np.mean(prev_closes))  # prev_closes已经是前5天了
                
                if current_price > current_ma5:  # 突破MA5
                    # 检查敏感度
                    sensitivity_level = 'unknown'
                    sensitivity_allowed = True
                    if self.sensitivity_analyzer and self.buy_sensitivity_config:
                        try:
                            sensitivity_level = self.sensitivity_analyzer.analyze(time_obj, 'medium')
                            buy_rule = self.buy_sensitivity_config.get(sensitivity_level, {})
                            sensitivity_allowed = buy_rule.get('allowed', True)
                        except:
                            pass
                    
                    breakthrough_moments.append({
                        'time': time_obj.strftime('%H:%M:%S'),
                        'price': current_price,
                        'ma5': current_ma5,
                        'sensitivity': sensitivity_level,
                        'sensitivity_allowed': sensitivity_allowed
                    })
            
            if breakthrough_moments:
                print(f"\n         ✅ 找到 {len(breakthrough_moments)} 个时刻价格突破MA5（用于突破判断的MA5）:")
                
                # 显示前3个
                for i, moment in enumerate(breakthrough_moments[:3], 1):
                    sens_emoji = "✅" if moment['sensitivity_allowed'] else "🚫"
                    sens_desc = "允许" if moment['sensitivity_allowed'] else "禁止"
                    print(f"            {i}. {moment['time']} - 价格:{moment['price']:.2f} > MA5_突破:{moment['ma5']:.2f}")
                    print(f"               敏感度: {moment['sensitivity']} ({sens_emoji} {sens_desc})")
                
                if len(breakthrough_moments) > 3:
                    print(f"            ... 还有 {len(breakthrough_moments)-3} 个时刻")
                
                # 统计敏感度分布
                blocked_by_sensitivity = [m for m in breakthrough_moments if not m['sensitivity_allowed']]
                allowed_by_sensitivity = [m for m in breakthrough_moments if m['sensitivity_allowed']]
                
                print(f"\n         📊 统计:")
                print(f"            突破MA5的时刻: {len(breakthrough_moments)} 个")
                print(f"            被敏感度过滤: {len(blocked_by_sensitivity)} 个")
                print(f"            通过敏感度: {len(allowed_by_sensitivity)} 个")
                
                if len(allowed_by_sensitivity) > 0:
                    print(f"\n         ⚠️  有 {len(allowed_by_sensitivity)} 个时刻既突破MA5又通过敏感度")
                    print(f"             但仍被策略过滤，可能原因:")
                    print(f"             • 量价关系不符合（需要放量配合）")
                    print(f"             • 量价背离检测未通过")
                    print(f"             • 冷静期限制（2小时内不重复买入）")
                    print(f"             • 其他策略内部条件")
                elif len(blocked_by_sensitivity) > 0:
                    print(f"\n         💡 结论: 所有突破MA5的时刻都在高风险敏感期")
                    print(f"             这是敏感度过滤机制正常工作，避免了假突破")
            else:
                print(f"\n         ❌ 全天没有任何时刻价格突破MA5")
                max_price = minute_data['close'].max()
                max_ma5 = float(np.mean(prev_closes[-4:] + [max_price]))
                print(f"            最高价: {max_price:.2f}")
                print(f"            对应MA5: {max_ma5:.2f}")
                print(f"            差距: {max_price - max_ma5:.2f}元")
        
        # ⭐ 返回触发信息（用于参数优化）
        formatted_triggers = []
        for candidate in buy_candidates:
            formatted_triggers.append({
                'time': candidate.get('time_obj'),
                'price': candidate['price'],
                'ma5': candidate['ma5']
            })
        return formatted_triggers
    
    def _summarize_results(self, results):
        """汇总诊断结果"""
        print(f"\n{'=' * 80}")
        print("[诊断汇总]")
        print("=" * 80)
        
        total_days = len(results)
        strategy_triggered = sum(1 for r in results if r.get('strategy_result', {}).get('triggered', False))
        tech_triggered = sum(1 for r in results if len(r.get('tech_result', {}).get('signals', [])) > 0)
        
        print(f"  总交易日: {total_days}天")
        print(f"  主策略触发: {strategy_triggered}天 ({strategy_triggered/total_days*100:.1f}%)" if total_days > 0 else "  主策略触发: 0天")
        print(f"  技术形态触发: {tech_triggered}天 ({tech_triggered/total_days*100:.1f}%)" if total_days > 0 else "  技术形态触发: 0天")
        
        # 参数建议汇总
        all_suggestions = []
        for r in results:
            all_suggestions.extend(r.get('suggestions', []))
        
        if all_suggestions:
            print(f"\n  [建议汇总] 参数调整建议 (基于{len(all_suggestions)}条分析):")
            
            # 按参数分组统计
            param_counts = {}
            for s in all_suggestions:
                param = s['parameter']
                param_counts[param] = param_counts.get(param, 0) + 1
            
            # 输出高频建议
            for param, count in sorted(param_counts.items(), key=lambda x: x[1], reverse=True):
                print(f"     - {param}: 出现{count}次")


def main():
    """命令行入口"""
    parser = argparse.ArgumentParser(description='策略诊断分析工具')
    parser.add_argument('--stock', type=str, help='股票代码 (如 002594.SZ)')
    parser.add_argument('--dates', type=str, nargs='+', help='诊断日期列表 (YYYYMMDD列表，如: --dates 20250526 或 --dates 20250521 20250523)')
    parser.add_argument('--start', type=str, help='起始日期 (YYYYMMDD)')
    parser.add_argument('--end', type=str, help='结束日期 (YYYYMMDD)')
    parser.add_argument('--signal', type=str, choices=['buy', 'sell'], help='信号类型')
    parser.add_argument('--dividend-base', type=str, help='前复权基准日 (YYYYMMDD，应与回测结束日期一致)')
    
    args = parser.parse_args()
    
    # 使用默认配置或命令行参数
    stock = args.stock if args.stock else DEFAULT_CONFIG['stock']
    start = args.start if args.start else DEFAULT_CONFIG['start']
    end = args.end if args.end else DEFAULT_CONFIG['end']
    dates = args.dates if args.dates else DEFAULT_CONFIG.get('dates')
    signal = args.signal if args.signal else DEFAULT_CONFIG['signal']
    dividend_base = args.dividend_base if args.dividend_base else DEFAULT_CONFIG.get('dividend_base')
    
    # 创建诊断工具
    tool = StrategyDiagnosticTool(stock, dividend_base=dividend_base)
    
    # 执行诊断
    if dates:
        if len(dates) == 1:
            # 单个日期，使用单日诊断
            tool.diagnose_single_day(dates[0], signal)
        else:
            # 多个日期，使用参数优化
            tool.optimize_parameters_for_dates(dates, signal)
    elif start and end:
        # 范围诊断
        tool.diagnose_range(start, end, signal)
    else:
        print("[错误] 请在代码中设置DEFAULT_CONFIG或使用命令行参数")
        print("      支持: --dates (单日或多日) | --start/--end (范围)")
        parser.print_help()


if __name__ == '__main__':
    main()

